utils and samples
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue Aug 29 17:47:17 2006 +0200 (2006-08-29)
changeset 12917ba023c576
parent 11 5bb7bce13924
child 13 b69ebc273a06
utils and samples
samples/main-callback.cc
samples/main-event.cc
samples/main-packet.cc
samples/main-simulator.cc
samples/main-trace.cc
utils/bench-packets.cc
utils/bench-simulator.cc
utils/grid.py
utils/replay-simulation.cc
utils/run-tests.cc
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/samples/main-callback.cc	Tue Aug 29 17:47:17 2006 +0200
     1.3 @@ -0,0 +1,58 @@
     1.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
     1.5 +#include "yans/callback.h"
     1.6 +#include <cassert>
     1.7 +#include <iostream>
     1.8 +
     1.9 +using namespace yans;
    1.10 +
    1.11 +static double 
    1.12 +cb_one (double a, double b)
    1.13 +{
    1.14 +	std::cout << "invoke cb_one a=" << a << ", b=" << b << std::endl;
    1.15 +	return a;
    1.16 +}
    1.17 +
    1.18 +class MyCb {
    1.19 +public:
    1.20 +	int cb_two (double a) {
    1.21 +		std::cout << "invoke cb_two a=" << a << std::endl;
    1.22 +		return -5;
    1.23 +	}
    1.24 +};
    1.25 +
    1.26 +
    1.27 +int main (int argc, char *argv[])
    1.28 +{
    1.29 +	// return type: double
    1.30 +	// first arg type: double
    1.31 +	// second arg type: double
    1.32 +	Callback<double, double, double> one;
    1.33 +	// build callback instance which points to cb_one function
    1.34 +	one = make_callback (&cb_one);
    1.35 +	// this is not a null callback
    1.36 +	assert (!one.is_null ());
    1.37 +	// invoke cb_one function through callback instance
    1.38 +	double ret_one;
    1.39 +	ret_one = one (10.0, 20.0);
    1.40 +
    1.41 +	// return type: int
    1.42 +	// first arg type: double
    1.43 +	Callback<int, double> two;
    1.44 +	MyCb cb;
    1.45 +	// build callback instance which points to MyCb::cb_two
    1.46 +	two = make_callback (&MyCb::cb_two, &cb);
    1.47 +	// this is not a null callback
    1.48 +	assert (!two.is_null ());
    1.49 +	// invoke MyCb::cb_two through callback instance
    1.50 +	int ret_two;
    1.51 +	ret_two = two (10.0);	
    1.52 +
    1.53 +	two = make_null_callback<int, double> ();
    1.54 +	// invoking a null callback is just like
    1.55 +	// invoking a null function pointer:
    1.56 +	// it will crash.
    1.57 +	//int ret_two_null = two (20.0);
    1.58 +	assert (two.is_null ());
    1.59 +
    1.60 +	return 0;
    1.61 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/samples/main-event.cc	Tue Aug 29 17:47:17 2006 +0200
     2.3 @@ -0,0 +1,42 @@
     2.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
     2.5 +#include "yans/event.h"
     2.6 +#include "yans/event.tcc"
     2.7 +#include <iostream>
     2.8 +
     2.9 +using namespace yans;
    2.10 +
    2.11 +class MyModel {
    2.12 +public:
    2.13 +	void deal_with_event (double event_value);
    2.14 +};
    2.15 +
    2.16 +void
    2.17 +MyModel::deal_with_event (double value)
    2.18 +{
    2.19 +	std::cout << "Member method received event." << std::endl;
    2.20 +}
    2.21 +
    2.22 +static void 
    2.23 +random_function (void)
    2.24 +{
    2.25 +	std::cout << "Function received event." << std::endl;
    2.26 +}
    2.27 +
    2.28 +
    2.29 +int main (int argc, char *argv[])
    2.30 +{
    2.31 +	Event ev;
    2.32 +	// create event to forward to random_function
    2.33 +	ev = make_event (&random_function);
    2.34 +	// set cancel bit to on
    2.35 +	ev.cancel ();
    2.36 +	// try to invoke the random_function through the event.
    2.37 +	// This does nothing since cancel bit is on.
    2.38 +	ev ();
    2.39 +	MyModel model;
    2.40 +	// create event to forward to MyModel::deal_with_event
    2.41 +	// on the class instance "model".
    2.42 +	ev = make_event (&MyModel::deal_with_event, &model, 10.0);
    2.43 +	// invoke member method through the event.
    2.44 +	ev ();
    2.45 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/samples/main-packet.cc	Tue Aug 29 17:47:17 2006 +0200
     3.3 @@ -0,0 +1,100 @@
     3.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
     3.5 +#include "yans/packet.h"
     3.6 +#include "yans/chunk.h"
     3.7 +#include <iostream>
     3.8 +
     3.9 +using namespace yans;
    3.10 +
    3.11 +/* A sample Chunk implementation
    3.12 + */
    3.13 +class MyChunk : public Chunk {
    3.14 +public:
    3.15 +	MyChunk ();
    3.16 +	virtual ~MyChunk ();
    3.17 +
    3.18 +	void set_data (uint16_t data);
    3.19 +	uint16_t get_data (void) const;
    3.20 +private:
    3.21 +	virtual void print (std::ostream *os) const;
    3.22 +	virtual void add_to (Buffer *buffer) const;
    3.23 +	virtual void peek_from (Buffer const *buffer);
    3.24 +	virtual void remove_from (Buffer *buffer);
    3.25 +
    3.26 +	uint16_t m_data;
    3.27 +};
    3.28 +
    3.29 +MyChunk::MyChunk ()
    3.30 +{}
    3.31 +MyChunk::~MyChunk ()
    3.32 +{}
    3.33 +void 
    3.34 +MyChunk::print (std::ostream *os) const
    3.35 +{
    3.36 +	*os << "MyChunk data=" << m_data << std::endl;
    3.37 +}
    3.38 +void 
    3.39 +MyChunk::add_to (Buffer *buffer) const
    3.40 +{
    3.41 +	// reserve 2 bytes at head of buffer
    3.42 +	buffer->add_at_start (2);
    3.43 +	Buffer::Iterator i = buffer->begin ();
    3.44 +	// serialize in head of buffer
    3.45 +	i.write_hton_u16 (m_data);
    3.46 +}
    3.47 +void 
    3.48 +MyChunk::peek_from (Buffer const *buffer)
    3.49 +{
    3.50 +	Buffer::Iterator i = buffer->begin ();
    3.51 +	// deserialize from head of buffer
    3.52 +	m_data = i.read_ntoh_u16 ();
    3.53 +}
    3.54 +void 
    3.55 +MyChunk::remove_from (Buffer *buffer)
    3.56 +{
    3.57 +	// remove deserialized data
    3.58 +	buffer->remove_at_start (2);
    3.59 +}
    3.60 +
    3.61 +void 
    3.62 +MyChunk::set_data (uint16_t data)
    3.63 +{
    3.64 +	m_data = data;
    3.65 +}
    3.66 +uint16_t 
    3.67 +MyChunk::get_data (void) const
    3.68 +{
    3.69 +	return m_data;
    3.70 +}
    3.71 +
    3.72 +/* A sample Tag implementation
    3.73 + */
    3.74 +struct MyTag {
    3.75 +	uint16_t m_stream_id;
    3.76 +};
    3.77 +
    3.78 +
    3.79 +static void
    3.80 +receive (Packet p)
    3.81 +{
    3.82 +	MyChunk my;
    3.83 +	p.peek (&my);
    3.84 +	p.remove (&my);
    3.85 +	std::cout << "received data=" << my.get_data () << std::endl;
    3.86 +	struct MyTag my_tag;
    3.87 +	p.peek_tag (&my_tag);
    3.88 +}
    3.89 +
    3.90 +
    3.91 +int main (int argc, char *argv[])
    3.92 +{
    3.93 +	Packet p;
    3.94 +	MyChunk my;
    3.95 +	my.set_data (2);
    3.96 +	std::cout << "send data=2" << std::endl;
    3.97 +	p.add (&my);
    3.98 +	struct MyTag my_tag;
    3.99 +	my_tag.m_stream_id = 5;
   3.100 +	p.add_tag (&my_tag);
   3.101 +	receive (p);
   3.102 +	return 0;
   3.103 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/samples/main-simulator.cc	Tue Aug 29 17:47:17 2006 +0200
     4.3 @@ -0,0 +1,46 @@
     4.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
     4.5 +#include "yans/event.h"
     4.6 +#include "yans/event.tcc"
     4.7 +#include "yans/simulator.h"
     4.8 +#include <iostream>
     4.9 +
    4.10 +using namespace yans;
    4.11 +
    4.12 +class MyModel {
    4.13 +public:
    4.14 +	void start (void);
    4.15 +private:
    4.16 +	void deal_with_event (double event_value);
    4.17 +};
    4.18 +
    4.19 +void 
    4.20 +MyModel::start (void)
    4.21 +{
    4.22 +	Simulator::schedule_rel_s (10.0, make_event (&MyModel::deal_with_event, 
    4.23 +						  this, Simulator::now_s ()));
    4.24 +}
    4.25 +void
    4.26 +MyModel::deal_with_event (double value)
    4.27 +{
    4.28 +	std::cout << "Member method received event at " << Simulator::now_s () << " started at " << value << std::endl;
    4.29 +}
    4.30 +
    4.31 +static void 
    4.32 +random_function (MyModel *model)
    4.33 +{
    4.34 +	std::cout << "random function received event at " << Simulator::now_s () << std::endl;
    4.35 +	model->start ();
    4.36 +}
    4.37 +
    4.38 +
    4.39 +int main (int argc, char *argv[])
    4.40 +{
    4.41 +	MyModel model;
    4.42 +
    4.43 +	Simulator::schedule_rel_s (10.0, make_event (&random_function, 
    4.44 +						     &model));
    4.45 +
    4.46 +	Simulator::run ();
    4.47 +
    4.48 +	Simulator::destroy ();
    4.49 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/samples/main-trace.cc	Tue Aug 29 17:47:17 2006 +0200
     5.3 @@ -0,0 +1,60 @@
     5.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
     5.5 +#include "yans/trace-container.h"
     5.6 +#include "yans/ui-traced-variable.tcc"
     5.7 +#include "yans/packet-logger.h"
     5.8 +#include "yans/trace-stream.h"
     5.9 +#include "yans/pcap-writer.h"
    5.10 +#include <iostream>
    5.11 +
    5.12 +using namespace yans;
    5.13 +
    5.14 +PacketLogger a;
    5.15 +UiTracedVariable<unsigned short> b;
    5.16 +TraceStream c;
    5.17 +CallbackLogger<double, int> d;
    5.18 +
    5.19 +void
    5.20 +register_all_trace_sources (TraceContainer *container)
    5.21 +{
    5.22 +	container->register_packet_logger ("source-a", &a);
    5.23 +	container->register_ui_variable ("source-b", &b);
    5.24 +	container->register_stream ("source-c", &c);
    5.25 +	container->register_callback ("source-d", &d);
    5.26 +}
    5.27 +void
    5.28 +generate_trace_events (void)
    5.29 +{
    5.30 +	// log en empty packet
    5.31 +	a.log (Packet ());
    5.32 +	b = 10;
    5.33 +	b += 100;
    5.34 +	b += 50;
    5.35 +	b = (unsigned short) -20;
    5.36 +	c << "this is a simple test b=" << b << std::endl;
    5.37 +	d (3.1415, 3);
    5.38 +}
    5.39 +
    5.40 +void
    5.41 +variable_event (uint64_t old, uint64_t cur)
    5.42 +{}
    5.43 +
    5.44 +void
    5.45 +callback_event (double a, int b)
    5.46 +{}
    5.47 +
    5.48 +
    5.49 +int main (int argc, char *argv[])
    5.50 +{
    5.51 +	TraceContainer traces;
    5.52 +	register_all_trace_sources (&traces);
    5.53 +	PcapWriter pcap;
    5.54 +	pcap.open ("trace-test.log");
    5.55 +	pcap.write_header_ethernet ();
    5.56 +	traces.set_packet_logger_callback ("source-a", 
    5.57 +					   make_callback (&PcapWriter::write_packet, &pcap));
    5.58 +	traces.set_ui_variable_callback ("source-b", make_callback (&variable_event));
    5.59 +	traces.set_stream ("source-c", &std::cout);
    5.60 +	traces.set_callback ("source-d", make_callback (&callback_event));
    5.61 +	generate_trace_events ();
    5.62 +	return 0;
    5.63 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/utils/bench-packets.cc	Tue Aug 29 17:47:17 2006 +0200
     6.3 @@ -0,0 +1,135 @@
     6.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
     6.5 +/*
     6.6 + * Copyright (c) 2006 INRIA
     6.7 + * All rights reserved.
     6.8 + *
     6.9 + * This program is free software; you can redistribute it and/or modify
    6.10 + * it under the terms of the GNU General Public License version 2 as
    6.11 + * published by the Free Software Foundation;
    6.12 + *
    6.13 + * This program is distributed in the hope that it will be useful,
    6.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.16 + * GNU General Public License for more details.
    6.17 + *
    6.18 + * You should have received a copy of the GNU General Public License
    6.19 + * along with this program; if not, write to the Free Software
    6.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.21 + *
    6.22 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    6.23 + */
    6.24 +#include "yans/wall-clock-ms.h"
    6.25 +#include "yans/packet.h"
    6.26 +#include "yans/chunk-constant-data.h"
    6.27 +#include "yans/chunk-udp.h"
    6.28 +#include "yans/chunk-ipv4.h"
    6.29 +#include <iostream>
    6.30 +
    6.31 +using namespace yans;
    6.32 +
    6.33 +static void 
    6.34 +bench_ptr_a (uint32_t n)
    6.35 +{
    6.36 +	ChunkConstantData data = ChunkConstantData (2000, 1);
    6.37 +	ChunkUdp udp;
    6.38 +	ChunkIpv4 ipv4;
    6.39 +
    6.40 +	for (uint32_t i = 0; i < n; i++) {
    6.41 +		Packet p;
    6.42 +		p.add (&data);
    6.43 +		p.add (&udp);
    6.44 +		p.add (&ipv4);
    6.45 +		Packet o = p;
    6.46 +		o.peek (&ipv4);
    6.47 +		o.remove (&ipv4);
    6.48 +		o.peek (&udp);
    6.49 +		o.remove (&udp);
    6.50 +		o.peek (&data);
    6.51 +		o.remove (&data);
    6.52 +	}
    6.53 +}
    6.54 +
    6.55 +static void 
    6.56 +bench_ptr_b (uint32_t n)
    6.57 +{
    6.58 +	ChunkConstantData data = ChunkConstantData (2000, 1);
    6.59 +	ChunkUdp udp;
    6.60 +	ChunkIpv4 ipv4;
    6.61 +
    6.62 +	for (uint32_t i = 0; i < n; i++) {
    6.63 +		Packet p;
    6.64 +		p.add (&data);
    6.65 +		p.add (&udp);
    6.66 +		p.add (&ipv4);
    6.67 +	}
    6.68 +}
    6.69 +
    6.70 +static void
    6.71 +ptr_c2 (Packet p)
    6.72 +{
    6.73 +	ChunkConstantData data = ChunkConstantData (2000, 1);
    6.74 +	ChunkUdp udp;
    6.75 +
    6.76 +	p.peek (&udp);
    6.77 +	p.remove (&udp);
    6.78 +	p.peek (&data);
    6.79 +	p.remove (&data);
    6.80 +}
    6.81 +
    6.82 +static void 
    6.83 +ptr_c1 (Packet p)
    6.84 +{
    6.85 +	ChunkIpv4 ipv4;
    6.86 +	p.peek (&ipv4);
    6.87 +	p.remove (&ipv4);
    6.88 +	ptr_c2 (p);
    6.89 +}
    6.90 +
    6.91 +static void
    6.92 +bench_ptr_c (uint32_t n)
    6.93 +{
    6.94 +	ChunkConstantData data = ChunkConstantData (2000, 1);
    6.95 +	ChunkUdp udp;
    6.96 +	ChunkIpv4 ipv4;
    6.97 +
    6.98 +	for (uint32_t i = 0; i < n; i++) {
    6.99 +		Packet p;
   6.100 +		p.add (&data);
   6.101 +		p.add (&udp);
   6.102 +		p.add (&ipv4);
   6.103 +		ptr_c1 (p);
   6.104 +	}
   6.105 +}
   6.106 +
   6.107 +
   6.108 +static void
   6.109 +run_bench (void (*bench) (uint32_t), uint32_t n, char const *name)
   6.110 +{
   6.111 +	WallClockMs time;
   6.112 +	time.start ();
   6.113 +	(*bench) (n);
   6.114 +	unsigned long long delta_ms = time.end ();
   6.115 +	double ps = n;
   6.116 +	ps *= 1000;
   6.117 +	ps /= delta_ms;
   6.118 +	std::cout << name<<"=" << ps << " packets/s" << std::endl;
   6.119 +}
   6.120 +
   6.121 +int main (int argc, char *argv[])
   6.122 +{
   6.123 +	uint32_t n = 0;
   6.124 +	while (argc > 0) {
   6.125 +		if (strncmp ("--n=", argv[0],strlen ("--n=")) == 0) {
   6.126 +			char const *n_ascii = argv[0] + strlen ("--n=");
   6.127 +			n = atoi (n_ascii);
   6.128 +		}
   6.129 +		argc--;
   6.130 +		argv++;
   6.131 +	}
   6.132 +
   6.133 +	run_bench (&bench_ptr_a, n, "a");
   6.134 +	run_bench (&bench_ptr_b, n, "b");
   6.135 +	run_bench (&bench_ptr_c, n, "c");
   6.136 +
   6.137 +	return 0;
   6.138 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/utils/bench-simulator.cc	Tue Aug 29 17:47:17 2006 +0200
     7.3 @@ -0,0 +1,148 @@
     7.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
     7.5 +/*
     7.6 + * Copyright (c) 2006 INRIA
     7.7 + * All rights reserved.
     7.8 + *
     7.9 + * This program is free software; you can redistribute it and/or modify
    7.10 + * it under the terms of the GNU General Public License version 2 as
    7.11 + * published by the Free Software Foundation;
    7.12 + *
    7.13 + * This program is distributed in the hope that it will be useful,
    7.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.16 + * GNU General Public License for more details.
    7.17 + *
    7.18 + * You should have received a copy of the GNU General Public License
    7.19 + * along with this program; if not, write to the Free Software
    7.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.21 + *
    7.22 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    7.23 + */
    7.24 +
    7.25 +#include "yans/simulator.h"
    7.26 +#include "yans/event.h"
    7.27 +#include "yans/event.tcc"
    7.28 +#include "yans/wall-clock-ms.h"
    7.29 +#include <iostream>
    7.30 +#include <fstream>
    7.31 +#include <vector>
    7.32 +
    7.33 +using namespace yans;
    7.34 +
    7.35 +
    7.36 +bool g_debug = false;
    7.37 +
    7.38 +class Bench {
    7.39 +public:
    7.40 +	void read_distribution (std::istream &istream);
    7.41 +	void set_total (uint32_t total);
    7.42 +	void bench (void);
    7.43 +private:
    7.44 +	void cb (void);
    7.45 +	std::vector<uint64_t> m_distribution;
    7.46 +	std::vector<uint64_t>::const_iterator m_current;
    7.47 +	uint32_t m_n;
    7.48 +	uint32_t m_total;
    7.49 +};
    7.50 +
    7.51 +void 
    7.52 +Bench::set_total (uint32_t total)
    7.53 +{
    7.54 +	m_total = total;
    7.55 +}
    7.56 +
    7.57 +void
    7.58 +Bench::read_distribution (std::istream &input)
    7.59 +{
    7.60 +	double data;
    7.61 +	while (!input.eof ()) {
    7.62 +		if (input >> data) {
    7.63 +			uint64_t us = (uint64_t) (data * 1000000);
    7.64 +			m_distribution.push_back (us);
    7.65 +		} else {
    7.66 +			input.clear ();
    7.67 +			std::string line;
    7.68 +			input >> line;
    7.69 +		}
    7.70 +	}
    7.71 +}
    7.72 +
    7.73 +void
    7.74 +Bench::bench (void) 
    7.75 +{
    7.76 +	WallClockMs time;
    7.77 +	double init, simu;
    7.78 +	time.start ();
    7.79 +	for (std::vector<uint64_t>::const_iterator i = m_distribution.begin ();
    7.80 +	     i != m_distribution.end (); i++) {
    7.81 +		Simulator::schedule_rel_us (*i, make_event (&Bench::cb, this));
    7.82 +	}
    7.83 +	init = time.end ();
    7.84 +
    7.85 +	m_current = m_distribution.begin ();
    7.86 +
    7.87 +	time.start ();
    7.88 +	Simulator::run ();
    7.89 +	simu = time.end ();
    7.90 +
    7.91 +	std::cout <<
    7.92 +		"init n=" << m_distribution.size () << ", time=" << init << "s" << std::endl <<
    7.93 +		"simu n=" << m_n << ", time=" <<simu << "s" << std::endl <<
    7.94 +		"init " << ((double)m_distribution.size ()) / init << " insert/s, avg insert=" <<
    7.95 +		init / ((double)m_distribution.size ())<< "s" << std::endl <<
    7.96 +		"simu " << ((double)m_n) / simu<< " hold/s, avg hold=" << 
    7.97 +		simu / ((double)m_n) << "s" << std::endl
    7.98 +		;
    7.99 +}
   7.100 +
   7.101 +void
   7.102 +Bench::cb (void)
   7.103 +{
   7.104 +	if (m_n > m_total) {
   7.105 +		return;
   7.106 +	}
   7.107 +	if (m_current == m_distribution.end ()) {
   7.108 +		m_current = m_distribution.begin ();
   7.109 +	}
   7.110 +	if (g_debug) {
   7.111 +		std::cerr << "event at " << Simulator::now_s () << std::endl;
   7.112 +	}
   7.113 +	Simulator::schedule_rel_us (*m_current, make_event (&Bench::cb, this));
   7.114 +	m_current++;
   7.115 +	m_n++;
   7.116 +}
   7.117 +
   7.118 +int main (int argc, char *argv[])
   7.119 +{
   7.120 +	char const *filename = argv[1];
   7.121 +	std::istream *input;
   7.122 +	argc-=2;
   7.123 +	argv+= 2;
   7.124 +	if (strcmp (filename, "-") == 0) {
   7.125 +		input = &std::cin;
   7.126 +	} else {
   7.127 +		input = new std::ifstream (filename);
   7.128 +	}
   7.129 +	while (argc > 0) {
   7.130 +		if (strcmp ("--list", argv[0]) == 0) {
   7.131 +			Simulator::set_linked_list ();
   7.132 +		} else if (strcmp ("--heap", argv[0]) == 0) {
   7.133 +			Simulator::set_binary_heap ();
   7.134 +		} else if (strcmp ("--map", argv[0]) == 0) {
   7.135 +			Simulator::set_std_map ();
   7.136 +		} else if (strcmp ("--debug", argv[0]) == 0) {
   7.137 +			g_debug = true;
   7.138 +		} else if (strncmp ("--log=", argv[0],strlen ("--log=")) == 0) {
   7.139 +			char const *filename = argv[0] + strlen ("--log=");
   7.140 +			Simulator::enable_log_to (filename);
   7.141 +		}
   7.142 +		argc--;
   7.143 +		argv++;
   7.144 +	}
   7.145 +	Bench *bench = new Bench ();
   7.146 +	bench->read_distribution (*input);
   7.147 +	bench->set_total (20000);
   7.148 +	bench->bench ();
   7.149 +
   7.150 +	return 0;
   7.151 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/utils/grid.py	Tue Aug 29 17:47:17 2006 +0200
     8.3 @@ -0,0 +1,1053 @@
     8.4 +#!/usr/bin/env python
     8.5 +
     8.6 +import cairo
     8.7 +import sys
     8.8 +import re
     8.9 +import gtk
    8.10 +
    8.11 +
    8.12 +
    8.13 +class DataRange:
    8.14 +    def __init__ (self, start = 0, end = 0, value = ''):
    8.15 +        self.start = start
    8.16 +        self.end = end
    8.17 +        self.value = value
    8.18 +class EventString:
    8.19 +    def __init__ (self, at = 0, value = ''):
    8.20 +        self.at = at
    8.21 +        self.value = value
    8.22 +class EventFloat:
    8.23 +    def __init__ (self, at = 0, value = 0.0):
    8.24 +        self.at = at
    8.25 +        self.value = value
    8.26 +class EventInt:
    8.27 +    def __init__ (self, at = 0, value = 0.0):
    8.28 +        self.at = at
    8.29 +        self.value = value
    8.30 +def ranges_cmp (a, b):
    8.31 +    return a.start - b.start
    8.32 +def events_cmp (a,b):
    8.33 +    return a.at - b.at
    8.34 +class TimelineDataRange:
    8.35 +    def __init__ (self, name = ''):
    8.36 +        self.name = name
    8.37 +        self.ranges = []
    8.38 +        return
    8.39 +    def __search (self, key):
    8.40 +        l = 0
    8.41 +        u = len (self.ranges)-1
    8.42 +        while l <= u:
    8.43 +            i = int ((l+u)/2)
    8.44 +            if key >= self.ranges[i].start and key <= self.ranges[i].end:
    8.45 +                return i
    8.46 +            elif key < self.ranges[i].start:
    8.47 +                u = i - 1
    8.48 +            else:
    8.49 +                # key > self.ranges[i].end
    8.50 +                l = i + 1
    8.51 +        return -1
    8.52 +    def add_range (self, range):
    8.53 +        self.ranges.append (range)
    8.54 +    def get_all (self):
    8.55 +        return self.ranges
    8.56 +    def get_ranges (self, start, end):
    8.57 +        s = self.__search (start)
    8.58 +        e = self.__search (end)
    8.59 +        if s == -1 and e == -1:
    8.60 +            return []
    8.61 +        elif s == -1:
    8.62 +            return self.ranges[0:e+1]
    8.63 +        elif e == -1:
    8.64 +            return self.ranges[s:len (self.ranges)]
    8.65 +        else:
    8.66 +            return self.ranges[s:e+1]
    8.67 +    def get_ranges_bounds (self, start, end):
    8.68 +        s = self.__search (start)
    8.69 +        e = self.__search (end)
    8.70 +        if s == -1 and e == -1:
    8.71 +            return (0,0)
    8.72 +        elif s == -1:
    8.73 +            return (0,e+1)
    8.74 +        elif e == -1:
    8.75 +            return (s, len (self.ranges))
    8.76 +        else:
    8.77 +            return (s,e+1)
    8.78 +    def sort (self):
    8.79 +        self.ranges.sort (ranges_cmp)
    8.80 +    def get_bounds (self):
    8.81 +        if len (self.ranges) > 0:
    8.82 +            lo = self.ranges[0].start
    8.83 +            hi = self.ranges[len (self.ranges)-1].end
    8.84 +            return (lo, hi)
    8.85 +        else:
    8.86 +            return (0,0)
    8.87 +class TimelineEvent:
    8.88 +    def __init__ (self, name = ''):
    8.89 +        self.name = name
    8.90 +        self.events = []
    8.91 +    def __search (self, key):
    8.92 +        l = 0
    8.93 +        u = len (self.events)-1
    8.94 +        while l <= u:
    8.95 +            i = int ((l+u)/2)
    8.96 +            if key == self.events[i].at:
    8.97 +                return i
    8.98 +            elif key < self.events[i].at:
    8.99 +                u = i - 1
   8.100 +            else:
   8.101 +                # key > self.events[i].at
   8.102 +                l = i + 1
   8.103 +        return l
   8.104 +    def add_event (self, event):
   8.105 +        self.events.append (event)
   8.106 +    def get_events (self, start, end):
   8.107 +        s = self.__search (start)
   8.108 +        e = self.__search (end)
   8.109 +        return self.events[s:e+1]
   8.110 +    def get_events_bounds (self, start, end):
   8.111 +        s = self.__search (start)
   8.112 +        e = self.__search (end)
   8.113 +        return (s, e+1)
   8.114 +    def sort (self):
   8.115 +        self.events.sort (events_cmp)
   8.116 +    def get_bounds (self):
   8.117 +        if len (self.events) > 0:
   8.118 +            lo = self.events[0].at
   8.119 +            hi = self.events[-1].at
   8.120 +            return (lo,hi)
   8.121 +        else:
   8.122 +            return (0,0)
   8.123 +
   8.124 +class Timeline:
   8.125 +    def __init__ (self, name = ''):
   8.126 +        self.ranges = []
   8.127 +        self.event_str = []
   8.128 +        self.event_int = []
   8.129 +        self.name = name
   8.130 +    def get_range (self, name):
   8.131 +        for range in self.ranges:
   8.132 +            if range.name == name:
   8.133 +                return range
   8.134 +        timeline = TimelineDataRange (name)
   8.135 +        self.ranges.append (timeline)
   8.136 +        return timeline
   8.137 +    def get_event_str (self, name):
   8.138 +        for event_str in self.event_str:
   8.139 +            if event_str.name == name:
   8.140 +                return event_str
   8.141 +        timeline = TimelineEvent (name)
   8.142 +        self.event_str.append (timeline)
   8.143 +        return timeline
   8.144 +    def get_event_int (self, name):
   8.145 +        for event_int in self.event_int:
   8.146 +            if event_int.name == name:
   8.147 +                return event_int
   8.148 +        timeline = TimelineEvent (name)
   8.149 +        self.event_int.append (timeline)
   8.150 +        return timeline
   8.151 +    def get_ranges (self):
   8.152 +        return self.ranges
   8.153 +    def get_events_str (self):
   8.154 +        return self.event_str
   8.155 +    def get_events_int (self):
   8.156 +        return self.event_int
   8.157 +    def sort (self):
   8.158 +        for range in self.ranges:
   8.159 +            range.sort ()
   8.160 +        for event in self.event_int:
   8.161 +            event.sort ()
   8.162 +        for event in self.event_str:
   8.163 +            event.sort ()
   8.164 +    def get_bounds (self):
   8.165 +        lo = 0
   8.166 +        hi = 0
   8.167 +        for range in self.ranges:
   8.168 +            (range_lo, range_hi) = range.get_bounds ()
   8.169 +            if range_lo < lo:
   8.170 +                lo = range_lo
   8.171 +            if range_hi > hi:
   8.172 +                hi = range_hi
   8.173 +        for event_str in self.event_str:
   8.174 +            (ev_lo, ev_hi) = event_str.get_bounds ()
   8.175 +            if ev_lo < lo:
   8.176 +                lo = ev_lo
   8.177 +            if ev_hi > hi:
   8.178 +                hi = ev_hi
   8.179 +        for event_int in self.event_int:
   8.180 +            (ev_lo, ev_hi) = event_int.get_bounds ()
   8.181 +            if ev_lo < lo:
   8.182 +                lo = ev_lo
   8.183 +            if ev_hi > hi:
   8.184 +                hi = ev_hi
   8.185 +        return (lo, hi)
   8.186 +class Timelines:
   8.187 +    def __init__ (self):
   8.188 +        self.timelines = []
   8.189 +    def get (self, name):
   8.190 +        for timeline in self.timelines:
   8.191 +            if timeline.name == name:
   8.192 +                return timeline
   8.193 +        timeline = Timeline (name)
   8.194 +        self.timelines.append (timeline)
   8.195 +        return timeline
   8.196 +    def get_all (self):
   8.197 +        return self.timelines
   8.198 +    def sort (self):
   8.199 +        for timeline in self.timelines:
   8.200 +            timeline.sort ()
   8.201 +    def get_bounds (self):
   8.202 +        lo = 0
   8.203 +        hi = 0
   8.204 +        for timeline in self.timelines:
   8.205 +            (t_lo, t_hi) = timeline.get_bounds ()
   8.206 +            if t_lo < lo:
   8.207 +                lo = t_lo
   8.208 +            if t_hi > hi:
   8.209 +                hi = t_hi
   8.210 +        return (lo, hi)
   8.211 +    def get_all_range_values (self):
   8.212 +        range_values = {}
   8.213 +        for timeline in self.timelines:
   8.214 +            for ranges in timeline.get_ranges ():
   8.215 +                for ran in ranges.get_all ():
   8.216 +                    range_values[ran.value] = 1
   8.217 +        return range_values.keys ()
   8.218 +class Color:
   8.219 +    def __init__ (self, r = 0.0, g = 0.0, b = 0.0):
   8.220 +        self.r = r
   8.221 +        self.g = g
   8.222 +        self.b = b
   8.223 +    def set (self, r, g, b):
   8.224 +        self.r = r
   8.225 +        self.g = g
   8.226 +        self.b = b
   8.227 +class Colors:
   8.228 +    # XXX add more
   8.229 +    default_colors = [Color (1,0,0), Color (0,1,0), Color (0,0,1),Color (1,1,0), Color(1,0,1), Color (0,1,1)]
   8.230 +    def __init__ (self):
   8.231 +        self.__colors = {}
   8.232 +    def add (self, name, color):
   8.233 +        self.__colors[name] = color
   8.234 +    def lookup (self, name):
   8.235 +        if not self.__colors.has_key (name):
   8.236 +            self.add (name, self.default_colors.pop ())
   8.237 +        return self.__colors.get(name)
   8.238 +
   8.239 +
   8.240 +class TopLegendRenderer:
   8.241 +    def __init__ (self):
   8.242 +        self.__padding = 10
   8.243 +    def set_padding (self, padding):
   8.244 +        self.__padding = padding
   8.245 +    def set_legends (self, legends, colors):
   8.246 +        self.__legends = legends
   8.247 +        self.__colors = colors
   8.248 +    def layout (self, width):
   8.249 +        self.__width = width
   8.250 +        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1,1)
   8.251 +        ctx = cairo.Context(surface)
   8.252 +        line_height = 0
   8.253 +        total_height = self.__padding
   8.254 +        line_used = self.__padding
   8.255 +        for legend in self.__legends:
   8.256 +            (t_width, t_height) = ctx.text_extents (legend)[2:4]
   8.257 +            item_width = self.__padding +  self.__padding + t_width +  self.__padding
   8.258 +            item_height = t_height + self.__padding
   8.259 +            if item_height > line_height:
   8.260 +                line_height = item_height
   8.261 +            if line_used + item_width > self.__width:
   8.262 +                line_used = self.__padding + item_width
   8.263 +                total_height += line_height
   8.264 +            else:
   8.265 +                line_used += item_width
   8.266 +            x = line_used - item_width
   8.267 +        total_height += line_height
   8.268 +        self.__height = total_height
   8.269 +            
   8.270 +    def get_height (self):
   8.271 +        return self.__height
   8.272 +    def draw (self, ctx):
   8.273 +        i = 0
   8.274 +        line_height = 0
   8.275 +        total_height = self.__padding
   8.276 +        line_used = self.__padding
   8.277 +        for legend in self.__legends:
   8.278 +            (t_width, t_height) = ctx.text_extents (legend)[2:4]
   8.279 +            item_width = self.__padding +  self.__padding + t_width +  self.__padding
   8.280 +            item_height = t_height + self.__padding
   8.281 +            if item_height > line_height:
   8.282 +                line_height = item_height
   8.283 +            if line_used + item_width > self.__width:
   8.284 +                line_used = self.__padding + item_width
   8.285 +                total_height += line_height
   8.286 +            else:
   8.287 +                line_used += item_width
   8.288 +            x = line_used - item_width
   8.289 +            ctx.rectangle (x, total_height, self.__padding, self.__padding)
   8.290 +            ctx.set_source_rgb (0,0,0)
   8.291 +            ctx.set_line_width (2)
   8.292 +            ctx.stroke_preserve ()
   8.293 +            ctx.set_source_rgb (self.__colors[i].r,
   8.294 +                                self.__colors[i].g,
   8.295 +                                self.__colors[i].b)
   8.296 +            ctx.fill ()
   8.297 +            ctx.move_to (x+self.__padding*2, total_height+t_height)
   8.298 +            ctx.set_source_rgb (0,0,0)
   8.299 +            ctx.show_text (legend)
   8.300 +            i += 1
   8.301 +
   8.302 +        return
   8.303 +
   8.304 +class TimelinesRenderer:
   8.305 +    def __init__ (self):
   8.306 +        self.padding = 10
   8.307 +        return
   8.308 +    def get_height (self):
   8.309 +        return self.height
   8.310 +    def set_timelines (self, timelines, colors):
   8.311 +        self.timelines = timelines
   8.312 +        self.colors = colors
   8.313 +    def set_render_range (self, start, end):
   8.314 +        self.start = start
   8.315 +        self.end = end
   8.316 +    def get_data_x_start (self):
   8.317 +        return self.padding / 2 + self.left_width + self.padding + self.right_width + self.padding/2
   8.318 +    def layout (self, width):
   8.319 +        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1,1)
   8.320 +        ctx = cairo.Context(surface)
   8.321 +        max_text_height = ctx.text_extents ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcedefghijklmnopqrstuvwxyz0123456789")[3]
   8.322 +
   8.323 +        left_width = 0
   8.324 +        right_width = 0
   8.325 +        left_n_lines = 0
   8.326 +        range_n = 0
   8.327 +        eventint_n = 0
   8.328 +        eventstr_n = 0
   8.329 +        for timeline in self.timelines.get_all ():
   8.330 +            left_n_lines += 1
   8.331 +            t_width = ctx.text_extents (timeline.name)[2]
   8.332 +            left_width = max (left_width, t_width)
   8.333 +            for rang in timeline.get_ranges ():
   8.334 +                t_width = ctx.text_extents (rang.name)[2]
   8.335 +                right_width = max (right_width, t_width)
   8.336 +                range_n += 1
   8.337 +            for events_int in timeline.get_events_int ():
   8.338 +                t_width = ctx.text_extents (events_int.name)[2]
   8.339 +                right_width = max (right_width, t_width)
   8.340 +                eventint_n += 1
   8.341 +            for events_str in timeline.get_events_str ():
   8.342 +                t_width = ctx.text_extents (events_str.name)[2]
   8.343 +                right_width = max (right_width, t_width)
   8.344 +                eventstr_n += 1
   8.345 +
   8.346 +        left_height = left_n_lines * max_text_height + (left_n_lines - 1) * self.padding
   8.347 +        right_n_lines = range_n + eventint_n + eventstr_n
   8.348 +        right_height = (right_n_lines - 1) * self.padding + right_n_lines * max_text_height
   8.349 +        right_data_height = (eventint_n + eventstr_n) * (max_text_height + 5) + range_n * 10
   8.350 +        right_data_height += (right_n_lines - 1) * self.padding
   8.351 +
   8.352 +        height = max (left_height, right_height)
   8.353 +        height = max (height, right_data_height)
   8.354 +
   8.355 +        self.left_width = left_width
   8.356 +        self.right_width = right_width
   8.357 +        self.max_text_height = max_text_height
   8.358 +        self.width = width
   8.359 +        self.height = height + self.padding
   8.360 +    def draw_line (self, ctx, x, y, width, height):
   8.361 +        ctx.move_to (x, y)
   8.362 +        ctx.rel_line_to (width, height)
   8.363 +        ctx.close_path ()
   8.364 +        ctx.set_operator (cairo.OPERATOR_SOURCE)
   8.365 +        ctx.set_line_width (1.0)
   8.366 +        ctx.set_source_rgb (0,0,0)
   8.367 +        ctx.stroke ()
   8.368 +    def draw_events (self, ctx, events, x, y, width, height):
   8.369 +        if (self.grey_background % 2) == 0:
   8.370 +            ctx.rectangle (x, y-self.padding/2,
   8.371 +                           width, height+self.padding)
   8.372 +            ctx.set_source_rgb (0.9,0.9,0.9)
   8.373 +            ctx.fill ()
   8.374 +        last_x_drawn = int (x)
   8.375 +        (lo, hi) = events.get_events_bounds (self.start, self.end)
   8.376 +        for event in events.events[lo:hi]:
   8.377 +            real_x = int (x + (event.at - self.start) * width / (self.end - self.start))
   8.378 +            if real_x > last_x_drawn+2:
   8.379 +                ctx.rectangle (real_x, y, 1, 1)
   8.380 +                ctx.set_source_rgb (1,0,0)
   8.381 +                ctx.stroke ()
   8.382 +                ctx.move_to (real_x, y+self.max_text_height)
   8.383 +                ctx.set_source_rgb (0,0,0)
   8.384 +                ctx.show_text (str (event.value))
   8.385 +                last_x_drawn = real_x
   8.386 +        self.grey_background += 1
   8.387 +    def draw_ranges (self, ctx, ranges, x, y, width, height):
   8.388 +        if (self.grey_background % 2) == 0:
   8.389 +            ctx.rectangle (x, y-self.padding/2,
   8.390 +                           width, height+self.padding)
   8.391 +            ctx.set_source_rgb (0.9,0.9,0.9)
   8.392 +            ctx.fill ()
   8.393 +        last_x_drawn = int (x-1)
   8.394 +        (lo, hi) = ranges.get_ranges_bounds (self.start, self.end)
   8.395 +        for data_range in ranges.ranges[lo:hi]:
   8.396 +            s = max (data_range.start, self.start)
   8.397 +            e = min (data_range.end, self.end)
   8.398 +            x_start = int (x + (s - self.start) * width / (self.end - self.start))
   8.399 +            x_end = int (x + (e - self.start) * width / (self.end - self.start))
   8.400 +            if x_end > last_x_drawn:
   8.401 +                ctx.rectangle (x_start, y, x_end - x_start, 10)
   8.402 +                ctx.set_source_rgb (0,0,0)
   8.403 +                ctx.stroke_preserve ()
   8.404 +                color = self.colors.lookup (data_range.value)
   8.405 +                ctx.set_source_rgb (color.r, color.g, color.b)
   8.406 +                ctx.fill ()
   8.407 +                last_x_drawn = x_end
   8.408 +
   8.409 +        self.grey_background += 1
   8.410 +        
   8.411 +    def draw (self, ctx):
   8.412 +        timeline_top = 0
   8.413 +        top_y = self.padding / 2
   8.414 +        left_x_start = self.padding / 2
   8.415 +        left_x_end = left_x_start + self.left_width
   8.416 +        right_x_start = left_x_end + self.padding
   8.417 +        right_x_end = right_x_start + self.right_width
   8.418 +        data_x_start = right_x_end + self.padding /2
   8.419 +        data_x_end = self.width
   8.420 +        data_width = data_x_end - data_x_start
   8.421 +        cur_y = top_y
   8.422 +        self.draw_line (ctx, 0, 0, self.width, 0)
   8.423 +        self.grey_background = 1
   8.424 +        for timeline in self.timelines.get_all ():
   8.425 +            (y_bearing,t_width,t_height) = ctx.text_extents (timeline.name)[1:4]
   8.426 +            ctx.move_to (left_x_start, cur_y + self.max_text_height - (t_height+y_bearing))
   8.427 +            ctx.show_text (timeline.name);
   8.428 +            for events_int in timeline.get_events_int ():
   8.429 +                (y_bearing, t_width, t_height) = ctx.text_extents (events_int.name)[1:4]
   8.430 +                ctx.move_to (right_x_start, cur_y + self.max_text_height - (t_height+y_bearing))
   8.431 +                ctx.show_text (events_int.name)
   8.432 +                self.draw_events (ctx, events_int, data_x_start, cur_y, data_width, self.max_text_height+5)
   8.433 +                cur_y += self.max_text_height + 5 + self.padding
   8.434 +                self.draw_line (ctx, right_x_start-self.padding/2, cur_y - self.padding / 2,
   8.435 +                                self.right_width + self.padding, 0)
   8.436 +
   8.437 +            for events_str in timeline.get_events_str ():
   8.438 +                (y_bearing, t_width, t_height) = ctx.text_extents (events_str.name)[1:4]
   8.439 +                ctx.move_to (right_x_start, cur_y + self.max_text_height - (t_height+y_bearing))
   8.440 +                ctx.show_text (events_str.name)
   8.441 +                self.draw_events (ctx, events_str, data_x_start, cur_y, data_width, self.max_text_height+5)
   8.442 +                cur_y += self.max_text_height + 5 + self.padding
   8.443 +                self.draw_line (ctx, right_x_start-self.padding/2, cur_y - self.padding / 2,
   8.444 +                                self.right_width + self.padding, 0)
   8.445 +            for ranges in timeline.get_ranges ():
   8.446 +                (y_bearing, t_width, t_height) = ctx.text_extents (ranges.name)[1:4]
   8.447 +                ctx.move_to (right_x_start, cur_y + self.max_text_height - (t_height+y_bearing))
   8.448 +                ctx.show_text (ranges.name)
   8.449 +                self.draw_ranges (ctx, ranges, data_x_start, cur_y, data_width, 10)
   8.450 +                cur_y += self.max_text_height + self.padding
   8.451 +                self.draw_line (ctx, right_x_start-self.padding/2, cur_y - self.padding / 2,
   8.452 +                                self.right_width + self.padding, 0)
   8.453 +            self.draw_line (ctx, 0, cur_y - self.padding / 2,
   8.454 +                            self.width, 0)
   8.455 +        bot_y = cur_y - self.padding / 2
   8.456 +        self.draw_line (ctx, left_x_end+self.padding/2, 0,
   8.457 +                        0, bot_y)
   8.458 +        self.draw_line (ctx, right_x_end+self.padding/2, 0,
   8.459 +                        0, bot_y)
   8.460 +        return
   8.461 +
   8.462 +class ScaleRenderer:
   8.463 +    def __init__ (self):
   8.464 +        self.__top = 0
   8.465 +        return
   8.466 +    def set_bounds (self, lo, hi):
   8.467 +        self.__lo = lo
   8.468 +        self.__hi = hi
   8.469 +    def get_position (self, x):
   8.470 +        real_x = (x - self.__lo ) * self.__width / (self.__hi - self.__lo)
   8.471 +        return real_x
   8.472 +    def set_top (self):
   8.473 +        self.__top = 1
   8.474 +    def set_bot (self):
   8.475 +        self.__top = 0
   8.476 +    def layout (self, width):
   8.477 +        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1,1)
   8.478 +        ctx = cairo.Context(surface)
   8.479 +
   8.480 +        # calculate scale delta
   8.481 +        data_delta = self.__hi - self.__lo
   8.482 +        closest = 1
   8.483 +        while (closest*10) < data_delta:
   8.484 +            closest *= 10
   8.485 +        if (data_delta / closest) == 0:
   8.486 +            delta = closest
   8.487 +        elif (data_delta / closest) == 1:
   8.488 +            delta = closest / 10
   8.489 +        else:
   8.490 +            delta = closest
   8.491 +        start = self.__lo - (self.__lo % delta) + delta
   8.492 +        end = self.__hi - (self.__hi % delta)
   8.493 +
   8.494 +        self.__delta = delta
   8.495 +        self.__width = width
   8.496 +
   8.497 +        # calculate text height
   8.498 +        max_text_height = ctx.text_extents ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcedefghijklmnopqrstuvwxyz0123456789")[3]
   8.499 +        self.max_text_height = max_text_height
   8.500 +        height = max_text_height + 10
   8.501 +        self.__height = height
   8.502 +    
   8.503 +    def get_height (self):
   8.504 +        return self.__height
   8.505 +    def draw (self, ctx):
   8.506 +        delta = self.__delta
   8.507 +        start = self.__lo - (self.__lo % delta) + delta
   8.508 +        end = self.__hi - (self.__hi % delta)
   8.509 +
   8.510 +        if self.__top == 1:
   8.511 +            s = -1
   8.512 +        else:
   8.513 +            s = 1
   8.514 +        # print scale points
   8.515 +        ctx.set_source_rgb (0, 0, 0)
   8.516 +        ctx.set_line_width (1.0)
   8.517 +        ticks = range (int (start), int (end + delta), int (delta))
   8.518 +        for x in ticks:
   8.519 +            real_x = (x - self.__lo ) * self.__width / (self.__hi - self.__lo)
   8.520 +            ctx.move_to (real_x, 0)
   8.521 +            ctx.line_to (real_x, 5*s)
   8.522 +            ctx.close_path ()
   8.523 +            ctx.stroke ()
   8.524 +            (t_y_bearing, t_width, t_height) = ctx.text_extents (str (x))[1:4]
   8.525 +            if self.__top:
   8.526 +                text_delta = t_height + t_y_bearing
   8.527 +            else:
   8.528 +                text_delta = -t_y_bearing
   8.529 +            ctx.move_to (real_x - t_width/2, (5 + 5 + text_delta)*s)
   8.530 +            ctx.show_text (str (x))
   8.531 +        # draw subticks
   8.532 +        delta /= 10
   8.533 +        if delta > 0:
   8.534 +            start = self.__lo - (self.__lo % delta) + delta
   8.535 +            end = self.__hi - (self.__hi % delta)
   8.536 +            for x in range (int (start), int (end + delta), int (delta)):
   8.537 +                real_x = (x - self.__lo ) * self.__width / (self.__hi - self.__lo)
   8.538 +                ctx.move_to (real_x, 0)
   8.539 +                ctx.line_to (real_x, 3*s)
   8.540 +                ctx.close_path ()
   8.541 +                ctx.stroke ()
   8.542 +        
   8.543 +        
   8.544 +
   8.545 +class GraphicRenderer:
   8.546 +    def __init__(self, start, end):
   8.547 +        self.__start = float (start)
   8.548 +        self.__end = float (end)
   8.549 +        self.__mid_scale = ScaleRenderer ()
   8.550 +        self.__mid_scale.set_top ()
   8.551 +        self.__bot_scale = ScaleRenderer ()
   8.552 +        self.__bot_scale.set_bounds (start, end)
   8.553 +        self.__bot_scale.set_bot ()
   8.554 +        self.__width = 1
   8.555 +        self.__height = 1
   8.556 +    def get_width (self):
   8.557 +        return self.__width
   8.558 +    def get_height (self):
   8.559 +        return self.__height
   8.560 +    # return x, y, width, height
   8.561 +    def get_data_rectangle (self):
   8.562 +        y_start = self.__top_legend.get_height ()
   8.563 +        x_start = self.__data.get_data_x_start ()
   8.564 +        return (x_start, y_start, self.__width - x_start, self.__data.get_height ())
   8.565 +    def scale_data (self, x):
   8.566 +        x_start = self.__data.get_data_x_start ()
   8.567 +        x_scaled = x / (self.__width - x_start) * (self.__r_end - self.__r_start)
   8.568 +        return x_scaled
   8.569 +    # return x, y, width, height
   8.570 +    def get_selection_rectangle (self):
   8.571 +        y_start = self.__top_legend.get_height () + self.__data.get_height () + self.__mid_scale.get_height () + 20
   8.572 +        y_height = self.__bot_scale.get_height () + 20
   8.573 +        x_start = self.__bot_scale.get_position (self.__r_start)
   8.574 +        x_end = self.__bot_scale.get_position (self.__r_end)
   8.575 +        return (x_start,y_start,x_end-x_start,y_height)
   8.576 +    def scale_selection (self, x):
   8.577 +        x_scaled = x / self.__width * (self.__end - self.__start)
   8.578 +        return x_scaled
   8.579 +    def set_range (self,start, end):
   8.580 +        s = min (start, end)
   8.581 +        e = max (start, end)
   8.582 +        start = max (self.__start, s)
   8.583 +        end = min (self.__end, e)
   8.584 +        self.__r_start = start
   8.585 +        self.__r_end = end
   8.586 +        self.__data.set_render_range (start, end)
   8.587 +        self.__mid_scale.set_bounds (start, end)
   8.588 +        self.layout (self.__width, self.__height)
   8.589 +    def get_range (self):
   8.590 +        return (self.__r_start, self.__r_end)
   8.591 +    def set_data (self, data):
   8.592 +        self.__data = data
   8.593 +    def set_top_legend (self, top_legend):
   8.594 +        self.__top_legend = top_legend
   8.595 +    def layout (self, width, height):
   8.596 +        self.__width = width
   8.597 +        self.__height = height
   8.598 +        self.__top_legend.layout (width)
   8.599 +        top_legend_height = self.__top_legend.get_height ()
   8.600 +        self.__data.layout (width)
   8.601 +        self.__mid_scale.layout (width - self.__data.get_data_x_start ())
   8.602 +        self.__bot_scale.layout (width)
   8.603 +        return
   8.604 +    def __x_pixel (self, x, width):
   8.605 +        new_x = (x - self.__start) * width / (self.__end - self.__start)
   8.606 +        return new_x
   8.607 +    
   8.608 +    def draw (self, ctx):
   8.609 +        # default background is white
   8.610 +        ctx.save ()
   8.611 +        ctx.set_source_rgb (1, 1, 1)
   8.612 +        ctx.set_operator (cairo.OPERATOR_SOURCE)
   8.613 +        ctx.rectangle (0,0,self.__width,self.__height)
   8.614 +        ctx.fill ()
   8.615 +
   8.616 +        # top legend 
   8.617 +        ctx.save ()
   8.618 +        self.__top_legend.draw (ctx)
   8.619 +        top_legend_height = self.__top_legend.get_height ()
   8.620 +        ctx.restore ()
   8.621 +
   8.622 +        # separation line
   8.623 +        ctx.move_to (0, top_legend_height)
   8.624 +        ctx.line_to (self.__width, top_legend_height)
   8.625 +        ctx.close_path ()
   8.626 +        ctx.set_line_width (2)
   8.627 +        ctx.set_source_rgb (0,0,0)
   8.628 +        ctx.stroke ()
   8.629 +
   8.630 +        # data
   8.631 +        ctx.save ()
   8.632 +        ctx.translate (0,
   8.633 +                       top_legend_height)
   8.634 +        self.__data.draw (ctx)
   8.635 +        ctx.restore ()
   8.636 +
   8.637 +        # scale below data
   8.638 +        ctx.save ()
   8.639 +        ctx.translate (self.__data.get_data_x_start (),
   8.640 +                       top_legend_height + self.__data.get_height () + self.__mid_scale.get_height ())
   8.641 +        self.__mid_scale.draw (ctx)
   8.642 +        ctx.restore ()
   8.643 +
   8.644 +        height_used = top_legend_height + self.__data.get_height () + self.__mid_scale.get_height ()
   8.645 +
   8.646 +        # separation between scale and left pane
   8.647 +        ctx.move_to (self.__data.get_data_x_start (), height_used)
   8.648 +        ctx.rel_line_to (0, -self.__mid_scale.get_height ())
   8.649 +        ctx.close_path ()
   8.650 +        ctx.set_source_rgb (0,0,0)
   8.651 +        ctx.set_line_width (2)
   8.652 +        ctx.stroke ()
   8.653 +
   8.654 +        # separation below scale
   8.655 +        ctx.move_to (0, height_used)
   8.656 +        ctx.line_to (self.__width, height_used)
   8.657 +        ctx.close_path ()
   8.658 +        ctx.set_line_width (2)
   8.659 +        ctx.set_source_rgb (0,0,0)
   8.660 +        ctx.stroke ()
   8.661 +
   8.662 +        select_start = self.__bot_scale.get_position (self.__r_start)
   8.663 +        select_end = self.__bot_scale.get_position (self.__r_end)
   8.664 +
   8.665 +        # left connection between top scale and bottom scale
   8.666 +        ctx.move_to (0, height_used);
   8.667 +        ctx.line_to (self.__data.get_data_x_start (), height_used)
   8.668 +        ctx.line_to (select_start, height_used + 20)
   8.669 +        ctx.line_to (0, height_used + 20)
   8.670 +        ctx.line_to (0,height_used)
   8.671 +        ctx.set_source_rgb (0,0,0)
   8.672 +        ctx.set_line_width (1)
   8.673 +        ctx.stroke_preserve ()
   8.674 +        ctx.set_source_rgb (0.9,0.9,0.9)
   8.675 +        ctx.fill ()
   8.676 +
   8.677 +        # right connection between top scale and bottom scale
   8.678 +        ctx.move_to (self.__width, height_used)
   8.679 +        ctx.line_to (self.__width, height_used+20)
   8.680 +        ctx.line_to (select_end, height_used+20)
   8.681 +        ctx.line_to (self.__width, height_used)
   8.682 +        ctx.set_source_rgb (0,0,0)
   8.683 +        ctx.set_line_width (1)
   8.684 +        ctx.stroke_preserve ()
   8.685 +        ctx.set_source_rgb (0.9,0.9,0.9)
   8.686 +        ctx.fill ()
   8.687 +
   8.688 +        height_used += 20
   8.689 +
   8.690 +        # unused area background
   8.691 +        unused_start = self.__bot_scale.get_position (self.__r_start)
   8.692 +        unused_end = self.__bot_scale.get_position (self.__r_end)
   8.693 +        unused_height = self.__bot_scale.get_height () + 20
   8.694 +        ctx.rectangle (0, height_used,
   8.695 +                       unused_start,
   8.696 +                       unused_height)
   8.697 +        ctx.rectangle (unused_end,
   8.698 +                       height_used,
   8.699 +                       self.__width - unused_end,
   8.700 +                       unused_height)
   8.701 +        ctx.set_source_rgb (0.9,0.9,0.9)
   8.702 +        ctx.fill ()        
   8.703 +
   8.704 +        # border line around bottom scale
   8.705 +        ctx.move_to (unused_end, height_used)
   8.706 +        ctx.line_to (self.__width, height_used)
   8.707 +        ctx.line_to (self.__width, height_used + unused_height)
   8.708 +        ctx.line_to (0, height_used + unused_height)
   8.709 +        ctx.line_to (0, height_used)
   8.710 +        ctx.line_to (unused_start, height_used)
   8.711 +        ctx.close_path ()
   8.712 +        ctx.set_line_width (2)
   8.713 +        ctx.set_source_rgb (0,0,0)
   8.714 +        ctx.stroke ()
   8.715 +        ctx.move_to (unused_start, height_used)
   8.716 +        ctx.line_to (unused_end, height_used)
   8.717 +        ctx.close_path ()
   8.718 +        ctx.set_line_width (1)
   8.719 +        ctx.set_source_rgb (0.9,0.9,0.9)
   8.720 +        ctx.stroke ()
   8.721 +
   8.722 +        # unused area dot borders
   8.723 +        ctx.save ()
   8.724 +        ctx.move_to (max (unused_start, 2), height_used)
   8.725 +        ctx.rel_line_to (0,unused_height)
   8.726 +        ctx.move_to (min (unused_end, self.__width-2), height_used)
   8.727 +        ctx.rel_line_to (0, unused_height)
   8.728 +        ctx.set_dash ([5], 0)
   8.729 +        ctx.set_source_rgb (0,0,0)
   8.730 +        ctx.set_line_width (1)
   8.731 +        ctx.stroke ()
   8.732 +        ctx.restore ()
   8.733 +
   8.734 +        # bottom scale
   8.735 +        ctx.save ()
   8.736 +        ctx.translate (0, height_used)
   8.737 +        self.__bot_scale.draw (ctx)
   8.738 +        ctx.restore ()
   8.739 +
   8.740 +class GtkGraphicRenderer (gtk.DrawingArea):
   8.741 +    def __init__ (self, data):
   8.742 +        super (GtkGraphicRenderer, self).__init__ ()
   8.743 +        self.__data = data
   8.744 +        self.__moving_left = False
   8.745 +        self.__moving_right = False
   8.746 +        self.__moving_both = False
   8.747 +        self.__moving_top = False
   8.748 +        self.__force_full_redraw = True
   8.749 +        self.add_events (gtk.gdk.POINTER_MOTION_MASK)
   8.750 +        self.add_events (gtk.gdk.BUTTON_PRESS_MASK)
   8.751 +        self.add_events (gtk.gdk.BUTTON_RELEASE_MASK)
   8.752 +        self.connect ("expose_event", self.expose)
   8.753 +        self.connect ('size-allocate', self.size_allocate)
   8.754 +        self.connect ('motion-notify-event', self.motion_notify)
   8.755 +        self.connect ('button-press-event', self.button_press)
   8.756 +        self.connect ('button-release-event', self.button_release)
   8.757 +    def set_smaller_zoom (self):
   8.758 +        (start, end) = self.__data.get_range ()
   8.759 +        self.__data.set_range (start, start+(end-start)*2)
   8.760 +        self.__force_full_redraw = True
   8.761 +        self.queue_draw ()
   8.762 +    def set_bigger_zoom (self):
   8.763 +        (start, end) = self.__data.get_range ()
   8.764 +        self.__data.set_range (start, start+(end-start)/2)
   8.765 +        self.__force_full_redraw = True
   8.766 +        self.queue_draw ()
   8.767 +    def output_png (self, filename):
   8.768 +        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
   8.769 +                                     self.__data.get_width (),
   8.770 +                                     self.__data.get_height ())
   8.771 +        ctx = cairo.Context (self.__buffer_surface)
   8.772 +        self.__data.draw (ctx)
   8.773 +        surface.write_to_png (filename)
   8.774 +    def button_press (self, widget, event):
   8.775 +        (x, y, width, height) = self.__data.get_selection_rectangle ()
   8.776 +        (d_x, d_y, d_width, d_height) = self.__data.get_data_rectangle ()
   8.777 +        if event.y > y and event.y < y+height:
   8.778 +            if abs (event.x - x) < 5:
   8.779 +                self.__moving_left = True
   8.780 +                return True
   8.781 +            if abs (event.x - (x+width)) < 5:
   8.782 +                self.__moving_right = True
   8.783 +                return True
   8.784 +            if event.x > x and event.x < x+width:
   8.785 +                self.__moving_both = True
   8.786 +                self.__moving_both_start = event.x
   8.787 +                self.__moving_both_cur = event.x
   8.788 +                return True
   8.789 +        if event.y > d_y and event.y < (d_y + d_height):
   8.790 +            if event.x > d_x and event.x < (d_x + d_width):
   8.791 +                self.__moving_top = True
   8.792 +                self.__moving_top_start = event.x
   8.793 +                self.__moving_top_cur = event.x
   8.794 +                return True
   8.795 +        return False
   8.796 +    def button_release (self, widget, event):
   8.797 +        if self.__moving_left:
   8.798 +            self.__moving_left = False
   8.799 +            left = self.__data.scale_selection (self.__moving_left_cur)
   8.800 +            right = self.__data.get_range ()[1]
   8.801 +            self.__data.set_range (left, right)
   8.802 +            self.__force_full_redraw = True
   8.803 +            self.queue_draw ()
   8.804 +            return True
   8.805 +        if self.__moving_right:
   8.806 +            self.__moving_right = False
   8.807 +            right = self.__data.scale_selection (self.__moving_right_cur)
   8.808 +            left = self.__data.get_range ()[0]
   8.809 +            self.__data.set_range (left, right)
   8.810 +            self.__force_full_redraw = True
   8.811 +            self.queue_draw ()
   8.812 +            return True
   8.813 +        if self.__moving_both:
   8.814 +            self.__moving_both = False
   8.815 +            delta = self.__data.scale_selection (self.__moving_both_cur - self.__moving_both_start)
   8.816 +            (left, right) = self.__data.get_range ()
   8.817 +            self.__data.set_range (left+delta, right+delta)
   8.818 +            self.__force_full_redraw = True
   8.819 +            self.queue_draw ()
   8.820 +            return True
   8.821 +        if self.__moving_top:
   8.822 +            self.__moving_top = False
   8.823 +        return False
   8.824 +    def motion_notify (self, widget, event):
   8.825 +        (x, y, width, height) = self.__data.get_selection_rectangle ()
   8.826 +        if self.__moving_left:
   8.827 +            if event.x <= 0:
   8.828 +                self.__moving_left_cur = 0
   8.829 +            elif event.x >= x+width:
   8.830 +                self.__moving_left_cur = x+width
   8.831 +            else:
   8.832 +                self.__moving_left_cur = event.x
   8.833 +            self.queue_draw_area (0, int(y), int(self.__width), int(height))
   8.834 +            return True
   8.835 +        if self.__moving_right:
   8.836 +            if event.x >= self.__width:
   8.837 +                self.__moving_right = self.__width
   8.838 +            elif event.x < x:
   8.839 +                self.__moving_right_cur = x
   8.840 +            else:
   8.841 +                self.__moving_right_cur = event.x
   8.842 +            self.queue_draw_area (0, int(y), int(self.__width), int(height))
   8.843 +            return True
   8.844 +        if self.__moving_both:
   8.845 +            cur_e = self.__width - (x + width - self.__moving_both_start)
   8.846 +            cur_s = (self.__moving_both_start - x)
   8.847 +            if event.x < cur_s:
   8.848 +                self.__moving_both_cur = cur_s
   8.849 +            elif event.x > cur_e:
   8.850 +                self.__moving_both_cur = cur_e
   8.851 +            else:
   8.852 +                self.__moving_both_cur = event.x
   8.853 +            self.queue_draw_area (0, int(y), int(self.__width), int(height))
   8.854 +            return True
   8.855 +        if self.__moving_top:
   8.856 +            self.__moving_top_cur = event.x
   8.857 +            delta = self.__data.scale_data (self.__moving_top_start-self.__moving_top_cur)
   8.858 +            (left, right) = self.__data.get_range ()
   8.859 +            self.__data.set_range (left+delta, right+delta)
   8.860 +            self.__force_full_redraw = True
   8.861 +            self.__moving_top_start = event.x
   8.862 +            self.queue_draw ()
   8.863 +            return True
   8.864 +        (d_x, d_y, d_width, d_height) = self.__data.get_data_rectangle ()
   8.865 +        if event.y > y and event.y < y+height:
   8.866 +            if abs (event.x - x) < 5 or abs (event.x - (x+width)) < 5:
   8.867 +                widget.window.set_cursor (gtk.gdk.Cursor (gtk.gdk.SB_H_DOUBLE_ARROW))
   8.868 +                return True
   8.869 +            if event.x > x and event.x < x+width:
   8.870 +                widget.window.set_cursor (gtk.gdk.Cursor (gtk.gdk.FLEUR))
   8.871 +                return True
   8.872 +        if event.y > d_y and event.y < (d_y + d_height):
   8.873 +            if event.x > d_x and event.x < (d_x + d_width):
   8.874 +                widget.window.set_cursor (gtk.gdk.Cursor (gtk.gdk.FLEUR))
   8.875 +                return True
   8.876 +        widget.window.set_cursor (None)
   8.877 +        return False
   8.878 +    def size_allocate (self, widget, allocation):
   8.879 +        self.__width = allocation.width
   8.880 +        self.__height = allocation.height
   8.881 +        self.__data.layout (allocation.width, allocation.height)
   8.882 +        self.__force_full_redraw = True
   8.883 +        self.queue_draw ()
   8.884 +    def expose (self, widget, event):
   8.885 +        if self.__force_full_redraw:
   8.886 +            self.__buffer_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
   8.887 +                                                       self.__data.get_width (),
   8.888 +                                                       self.__data.get_height ())
   8.889 +            ctx = cairo.Context(self.__buffer_surface)
   8.890 +            self.__data.draw (ctx)
   8.891 +            self.__force_full_redraw = False
   8.892 +        ctx = widget.window.cairo_create()
   8.893 +        ctx.rectangle(event.area.x, event.area.y,
   8.894 +                      event.area.width, event.area.height)
   8.895 +        ctx.clip()
   8.896 +        ctx.set_source_surface (self.__buffer_surface)
   8.897 +        ctx.paint ()
   8.898 +        (x, y, width, height) = self.__data.get_selection_rectangle ()
   8.899 +        if self.__moving_left:
   8.900 +            ctx.move_to (max (self.__moving_left_cur, 2), y)
   8.901 +            ctx.rel_line_to (0, height)
   8.902 +            ctx.close_path ()
   8.903 +            ctx.set_line_width (1)
   8.904 +            ctx.set_source_rgb (0,0,0)
   8.905 +            ctx.stroke ()
   8.906 +        if self.__moving_right:
   8.907 +            ctx.move_to (min (self.__moving_right_cur, self.__width-2), y)
   8.908 +            ctx.rel_line_to (0, height)
   8.909 +            ctx.close_path ()
   8.910 +            ctx.set_line_width (1)
   8.911 +            ctx.set_source_rgb (0,0,0)
   8.912 +            ctx.stroke ()
   8.913 +        if self.__moving_both:
   8.914 +            delta_x = self.__moving_both_cur - self.__moving_both_start
   8.915 +            left_x = x + delta_x
   8.916 +            ctx.move_to (x+delta_x, y)
   8.917 +            ctx.rel_line_to (0, height)
   8.918 +            ctx.close_path ()
   8.919 +            ctx.move_to (x+width+delta_x, y)
   8.920 +            ctx.rel_line_to (0, height)
   8.921 +            ctx.close_path ()
   8.922 +            ctx.set_source_rgb (0,0,0)
   8.923 +            ctx.set_line_width (1)
   8.924 +            ctx.stroke ()
   8.925 +        return False
   8.926 +
   8.927 +class MainWindow:
   8.928 +    def __init__ (self):
   8.929 +        return
   8.930 +    def run (self, graphic):
   8.931 +        window = gtk.Window()
   8.932 +        self.__window = window
   8.933 +        window.set_default_size (200, 200)
   8.934 +        vbox = gtk.VBox ()
   8.935 +        window.add (vbox)
   8.936 +        render = GtkGraphicRenderer(graphic)
   8.937 +        self.__render = render
   8.938 +        vbox.pack_end (render, True, True, 0)
   8.939 +        hbox = gtk.HBox ()
   8.940 +        vbox.pack_start (hbox, False, False, 0)
   8.941 +        smaller_zoom = gtk.Button ("Zoom Out")
   8.942 +        smaller_zoom.connect ("clicked", self.__set_smaller_cb)
   8.943 +        hbox.pack_start (smaller_zoom)
   8.944 +        bigger_zoom = gtk.Button ("Zoom In")
   8.945 +        bigger_zoom.connect ("clicked", self.__set_bigger_cb)
   8.946 +        hbox.pack_start (bigger_zoom)
   8.947 +        output_png = gtk.Button ("Output Png")
   8.948 +        output_png.connect ("clicked", self.__output_png_cb)
   8.949 +        hbox.pack_start (output_png)
   8.950 +        window.connect('destroy', gtk.main_quit)
   8.951 +        window.show_all()
   8.952 +        #gtk.bindings_activate (gtk.main_quit, 'q', 0)
   8.953 +        gtk.main()
   8.954 +    def __set_smaller_cb (self, widget):
   8.955 +        self.__render.set_smaller_zoom ()
   8.956 +    def __set_bigger_cb (self, widget):
   8.957 +        self.__render.set_bigger_zoom ()
   8.958 +    def __output_png_cb (self, widget):
   8.959 +        dialog = gtk.FileChooserDialog ("Output Png", self.__window,
   8.960 +                                        gtk.FILE_CHOOSER_ACTION_SAVE, ("Save",1))
   8.961 +        self.__dialog = dialog
   8.962 +        dialog.set_default_response (1)
   8.963 +        dialog.connect ("response", self.__dialog_response_cb)
   8.964 +        dialog.show ()
   8.965 +        return
   8.966 +    def __dialog_response_cb (self, widget, response):
   8.967 +        if response == 1:
   8.968 +            filename = self.__dialog.get_filename ()
   8.969 +            self.__render.output_png (filename)
   8.970 +            widget.hide ()
   8.971 +        return
   8.972 +
   8.973 +
   8.974 +
   8.975 +def read_data(filename):
   8.976 +    timelines = Timelines ()
   8.977 +    colors = Colors ()
   8.978 +    fh = open(filename)
   8.979 +    m1 = re.compile ('range ([^ ]+) ([^ ]+) ([^ ]+) ([0-9]+) ([0-9]+)')
   8.980 +    m2 = re.compile ('event-str ([^ ]+) ([^ ]+) ([^ ]+) ([0-9]+)')
   8.981 +    m3 = re.compile ('event-int ([^ ]+) ([^ ]+) ([0-9]+) ([0-9]+)')
   8.982 +    m4 = re.compile ('color ([^ ]+) #([a-fA-F0-9]{2,2})([a-fA-F0-9]{2,2})([a-fA-F0-9]{2,2})')
   8.983 +    for line in fh.readlines():
   8.984 +        m = m1.match (line)
   8.985 +        if m:
   8.986 +            line_name = m.group (1)
   8.987 +            timeline = timelines.get (m.group (1))
   8.988 +            rang = timeline.get_range (m.group (2))
   8.989 +            data_range = DataRange ()
   8.990 +            data_range.value = m.group (3)
   8.991 +            data_range.start = int (m.group (4))
   8.992 +            data_range.end = int (m.group (5))
   8.993 +            rang.add_range (data_range)
   8.994 +            continue
   8.995 +        m = m2.match (line)
   8.996 +        if m:
   8.997 +            line_name = m.group (1)
   8.998 +            timeline = timelines.get (m.group (1))
   8.999 +            ev = timeline.get_event_str (m.group (2))
  8.1000 +            event = EventString ()
  8.1001 +            event.value = m.group (3)
  8.1002 +            event.at = int (m.group (4))
  8.1003 +            ev.add_event (event)
  8.1004 +            continue
  8.1005 +        m = m3.match (line)
  8.1006 +        if m:
  8.1007 +            line_name = m.group (1)
  8.1008 +            timeline = timelines.get (m.group (1))
  8.1009 +            ev = timeline.get_event_int (m.group (2))
  8.1010 +            event = EventInt ()
  8.1011 +            event.value = int (m.group (3))
  8.1012 +            event.at = int (m.group (4))
  8.1013 +            ev.add_event (event)
  8.1014 +            continue
  8.1015 +        
  8.1016 +        m = m4.match (line)
  8.1017 +        if m:
  8.1018 +            r = int (m.group (2), 16)
  8.1019 +            g = int (m.group (3), 16)
  8.1020 +            b = int (m.group (4), 16)
  8.1021 +            color = Color (r/255, g/255, b/255)
  8.1022 +            colors.add (m.group (1), color)
  8.1023 +            continue
  8.1024 +    timelines.sort ()
  8.1025 +    return (colors, timelines)
  8.1026 +
  8.1027 +
  8.1028 +
  8.1029 +def main():
  8.1030 +    (colors, timelines) = read_data (sys.argv[1])
  8.1031 +    (lower_bound, upper_bound) = timelines.get_bounds ()
  8.1032 +    graphic = GraphicRenderer (lower_bound, upper_bound)
  8.1033 +    top_legend = TopLegendRenderer ()
  8.1034 +    range_values = timelines.get_all_range_values ()
  8.1035 +    range_colors = []
  8.1036 +    for range_value in range_values:
  8.1037 +        range_colors.append (colors.lookup (range_value))
  8.1038 +    top_legend.set_legends (range_values,
  8.1039 +                            range_colors)
  8.1040 +    graphic.set_top_legend (top_legend)
  8.1041 +    data = TimelinesRenderer ()
  8.1042 +    data.set_timelines (timelines, colors)
  8.1043 +    graphic.set_data (data)
  8.1044 +
  8.1045 +    # default range
  8.1046 +    range_mid = (upper_bound - lower_bound) /2
  8.1047 +    range_width = (upper_bound - lower_bound) /10
  8.1048 +    range_lo = range_mid - range_width / 2
  8.1049 +    range_hi = range_mid + range_width / 2
  8.1050 +    graphic.set_range (range_lo, range_hi)
  8.1051 +
  8.1052 +    main_window = MainWindow ()
  8.1053 +    main_window.run (graphic)
  8.1054 +
  8.1055 +
  8.1056 +main ()
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/utils/replay-simulation.cc	Tue Aug 29 17:47:17 2006 +0200
     9.3 @@ -0,0 +1,265 @@
     9.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
     9.5 +/*
     9.6 + * Copyright (c) 2006 INRIA
     9.7 + * All rights reserved.
     9.8 + *
     9.9 + * This program is free software; you can redistribute it and/or modify
    9.10 + * it under the terms of the GNU General Public License version 2 as
    9.11 + * published by the Free Software Foundation;
    9.12 + *
    9.13 + * This program is distributed in the hope that it will be useful,
    9.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.16 + * GNU General Public License for more details.
    9.17 + *
    9.18 + * You should have received a copy of the GNU General Public License
    9.19 + * along with this program; if not, write to the Free Software
    9.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.21 + *
    9.22 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    9.23 + */
    9.24 +
    9.25 +#include "yans/simulator.h"
    9.26 +#include "yans/event.h"
    9.27 +#include "yans/event.tcc"
    9.28 +#include "yans/wall-clock-ms.h"
    9.29 +#include <vector>
    9.30 +#include <deque>
    9.31 +#include <fstream>
    9.32 +#include <iostream>
    9.33 +
    9.34 +using namespace yans;
    9.35 +
    9.36 +class LogReader {
    9.37 +public:
    9.38 +	void read_from_filename (char const *filename);
    9.39 +	void run (void);
    9.40 +	void print_stats (void);
    9.41 +private:
    9.42 +	struct Command {
    9.43 +		enum {
    9.44 +			REMOVE,
    9.45 +			INSERT,
    9.46 +			INSERT_LATER,
    9.47 +			INSERT_REMOVE
    9.48 +		} m_type;
    9.49 +		// uid at which this command is supposed to be executed.
    9.50 +		uint32_t m_uid;
    9.51 +		union {
    9.52 +			struct {
    9.53 +				// time at which the event is supposed to expire
    9.54 +				uint64_t m_ev_us;
    9.55 +			} insert;
    9.56 +			struct {
    9.57 +				// location in the array of events to remove where
    9.58 +				// to insert this event once it is inserted in 
    9.59 +				// the scheduler.
    9.60 +				uint32_t m_ev_loc; 
    9.61 +				// time at which the event is supposed to expire
    9.62 +				uint64_t m_ev_us;
    9.63 +			} insert_remove;
    9.64 +		};
    9.65 +	};
    9.66 +	void execute_log_commands (uint32_t uid);
    9.67 +
    9.68 +	typedef std::deque<struct Command> Commands;
    9.69 +	typedef std::deque<struct Command>::iterator CommandsI;
    9.70 +	typedef std::deque<Event > RemoveEvents;
    9.71 +	
    9.72 +
    9.73 +	Commands m_commands;
    9.74 +	CommandsI m_command;
    9.75 +	RemoveEvents m_remove_events;
    9.76 +	uint32_t m_uid;
    9.77 +};
    9.78 +
    9.79 +typedef std::vector<std::pair<uint32_t, uint32_t> > Removes;
    9.80 +typedef std::vector<std::pair<uint32_t, uint32_t> >::iterator RemovesI;
    9.81 +
    9.82 +void
    9.83 +LogReader::read_from_filename (char const *filename)
    9.84 +{
    9.85 +	std::ifstream log;
    9.86 +	std::cout << "read log..." << std::endl;
    9.87 +	Removes removes;
    9.88 +	log.open (filename);
    9.89 +	while (!log.eof ()) {
    9.90 +		std::string type;
    9.91 +		log >> type;
    9.92 +		if (type == "i") {
    9.93 +			uint32_t now_uid, ev_uid;
    9.94 +			uint64_t now_us, ev_us;
    9.95 +			log >> now_uid >> now_us >> ev_uid >> ev_us;
    9.96 +			struct Command cmd;
    9.97 +			cmd.m_type = Command::INSERT;
    9.98 +			cmd.m_uid = now_uid;
    9.99 +			cmd.insert.m_ev_us = ev_us;
   9.100 +			m_commands.push_back (cmd);
   9.101 +		} else if (type == "r") {
   9.102 +			uint32_t now_uid, ev_uid;
   9.103 +			uint64_t now_us, ev_us;
   9.104 +			log >> now_uid >> now_us >> ev_uid >> ev_us;
   9.105 +			struct Command cmd;
   9.106 +			cmd.m_type = Command::REMOVE;
   9.107 +			cmd.m_uid = now_uid;
   9.108 +			m_commands.push_back (cmd);
   9.109 +			removes.push_back (std::make_pair (now_uid, ev_uid));
   9.110 +		} else if (type == "il") {
   9.111 +			uint32_t now_uid, ev_uid;
   9.112 +			uint64_t now_us, ev_us;
   9.113 +			log >> now_uid >> now_us >> ev_uid >> ev_us;
   9.114 +			struct Command cmd;
   9.115 +			cmd.m_type = Command::INSERT_LATER;
   9.116 +			cmd.m_uid = now_uid;
   9.117 +			m_commands.push_back (cmd);
   9.118 +		}
   9.119 +	}
   9.120 +	log.close ();
   9.121 +
   9.122 +	std::cout << "gather insert removes..." << std::endl;
   9.123 +	for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) {
   9.124 +		if (i->m_type == Command::INSERT) {
   9.125 +			for (RemovesI j = removes.begin (); j != removes.end (); j++) {
   9.126 +				if (j->second == i->m_uid) {
   9.127 +					// this insert will be removed later.
   9.128 +					uint64_t us = i->insert.m_ev_us;
   9.129 +					uint32_t uid = i->m_uid;
   9.130 +					i->m_type = Command::INSERT_REMOVE;
   9.131 +					i->m_uid = uid;
   9.132 +					i->insert_remove.m_ev_us = us;
   9.133 +					i->insert_remove.m_ev_loc = j->first;
   9.134 +					break;
   9.135 +				}
   9.136 +			}
   9.137 +		}
   9.138 +	}
   9.139 +	std::cout << "calculate remove locations..." << std::endl;
   9.140 +	// calculate the final insert/remove location.
   9.141 +	for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) {
   9.142 +		if (i->m_type == Command::INSERT_REMOVE) {
   9.143 +			uint32_t loc = 0;
   9.144 +			for (CommandsI tmp = i; tmp != m_commands.end (); tmp++) {
   9.145 +				if (tmp->m_type == Command::REMOVE &&
   9.146 +				    tmp->m_uid == i->insert_remove.m_ev_loc) {
   9.147 +					i->insert_remove.m_ev_loc = loc;
   9.148 +					break;
   9.149 +				}
   9.150 +				loc++;
   9.151 +			}
   9.152 +		}
   9.153 +	}
   9.154 +}
   9.155 +void
   9.156 +LogReader::execute_log_commands (uint32_t uid)
   9.157 +{
   9.158 +	if (m_command == m_commands.end ()) {
   9.159 +		return;
   9.160 +	}
   9.161 +	//std::cout << "one event, uid=" <<m_uid<< std::endl;
   9.162 +	struct Command cmd = *m_command;
   9.163 +	//std::cout << "cmd uid=" <<cmd.m_uid<< std::endl;
   9.164 +	while (cmd.m_uid == uid) {
   9.165 +		m_command++;
   9.166 +		switch (cmd.m_type) {
   9.167 +		case Command::INSERT:
   9.168 +			//std::cout << "exec insert now=" << Simulator::now_us ()
   9.169 +			//<< ", time=" << cmd.insert.m_ev_us << std::endl;
   9.170 +			Simulator::schedule_abs_us (cmd.insert.m_ev_us, 
   9.171 +						 make_event (&LogReader::execute_log_commands, this, m_uid));
   9.172 +			m_uid++;
   9.173 +			break;
   9.174 +		case Command::INSERT_LATER:
   9.175 +			//std::cout << "exec insert later" << std::endl;
   9.176 +			Simulator::schedule_now (make_event (&LogReader::execute_log_commands, this, m_uid));
   9.177 +			m_uid++;
   9.178 +			break;
   9.179 +		case Command::REMOVE: {
   9.180 +			//std::cout << "exec remove" << std::endl;
   9.181 +			Event ev = m_remove_events.front ();
   9.182 +			m_remove_events.pop_front ();
   9.183 +			Simulator::remove (ev);
   9.184 +		} break;
   9.185 +		case Command::INSERT_REMOVE: {
   9.186 +			//std::cout << "exec insert remove" << std::endl;
   9.187 +			Event ev = make_event (&LogReader::execute_log_commands, this, m_uid);
   9.188 +			Simulator::schedule_abs_us (cmd.insert_remove.m_ev_us, ev);
   9.189 +			m_remove_events[cmd.insert_remove.m_ev_loc] = ev;
   9.190 +			m_uid++;
   9.191 +		} break;
   9.192 +		}
   9.193 +		cmd = *m_command;
   9.194 +	}
   9.195 +}
   9.196 +
   9.197 +void
   9.198 +LogReader::print_stats (void)
   9.199 +{
   9.200 +	uint32_t n_inserts = 0;
   9.201 +	uint32_t n_removes = 0;
   9.202 +	for (CommandsI i = m_commands.begin (); i != m_commands.end (); i++) {
   9.203 +		switch (i->m_type) {
   9.204 +		case Command::INSERT:
   9.205 +			n_inserts++;
   9.206 +			break;
   9.207 +		case Command::INSERT_LATER:
   9.208 +			n_inserts++;
   9.209 +			break;
   9.210 +		case Command::INSERT_REMOVE:
   9.211 +			n_inserts++;
   9.212 +			break;
   9.213 +		case Command::REMOVE:
   9.214 +			n_removes++;
   9.215 +			break;
   9.216 +		}
   9.217 +	}
   9.218 +	std::cout << "inserts="<<n_inserts<<", removes="<<n_removes<<std::endl;
   9.219 +	std::cout << "run simulation..."<<std::endl;
   9.220 +}
   9.221 +
   9.222 +void
   9.223 +LogReader::run (void)
   9.224 +{
   9.225 +	m_uid = 0;
   9.226 +	WallClockMs time;
   9.227 +	time.start ();
   9.228 +	m_command = m_commands.begin ();
   9.229 +	execute_log_commands (m_uid);
   9.230 +	Simulator::run ();
   9.231 +	unsigned long long delta = time.end ();
   9.232 +	double delay = ((double)delta)/1000;
   9.233 +	std::cout << "runtime="<<delay<<"s"<<std::endl;
   9.234 +}
   9.235 +
   9.236 +
   9.237 +int main (int argc, char *argv[])
   9.238 +{
   9.239 +	char const *input = 0;
   9.240 +	uint32_t n = 1;
   9.241 +	while (argc > 0) {
   9.242 +		if (strcmp ("--list", argv[0]) == 0) {
   9.243 +			Simulator::set_linked_list ();
   9.244 +		} else if (strcmp ("--heap", argv[0]) == 0) {
   9.245 +			Simulator::set_binary_heap ();
   9.246 +		} else if (strcmp ("--map", argv[0]) == 0) {
   9.247 +			Simulator::set_std_map ();
   9.248 +		} else if (strncmp ("--n=", argv[0], strlen("--n=")) == 0) {
   9.249 +			n = atoi (argv[0]+strlen ("--n="));
   9.250 +		} else if (strncmp ("--input=", argv[0],strlen ("--input=")) == 0) {
   9.251 +			input = argv[0] + strlen ("--input=");
   9.252 +		} else if (strncmp ("--log=", argv[0],strlen ("--log=")) == 0) {
   9.253 +			char const *filename = argv[0] + strlen ("--log=");
   9.254 +			Simulator::enable_log_to (filename);
   9.255 +		}
   9.256 +		argc--;
   9.257 +		argv++;
   9.258 +	}
   9.259 +	if (input == 0) {
   9.260 +		std::cerr << "need --input=[filename] option" << std::endl;
   9.261 +		return 1;
   9.262 +	}
   9.263 +	LogReader log;
   9.264 +	log.read_from_filename (input);
   9.265 +	for (uint32_t i = 0; i < n; i++) {
   9.266 +		log.run ();
   9.267 +	}
   9.268 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/utils/run-tests.cc	Tue Aug 29 17:47:17 2006 +0200
    10.3 @@ -0,0 +1,32 @@
    10.4 +/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
    10.5 +/*
    10.6 + * Copyright (c) 2005 INRIA
    10.7 + * All rights reserved.
    10.8 + *
    10.9 + * This program is free software; you can redistribute it and/or modify
   10.10 + * it under the terms of the GNU General Public License version 2 as
   10.11 + * published by the Free Software Foundation;
   10.12 + *
   10.13 + * This program is distributed in the hope that it will be useful,
   10.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.16 + * GNU General Public License for more details.
   10.17 + *
   10.18 + * You should have received a copy of the GNU General Public License
   10.19 + * along with this program; if not, write to the Free Software
   10.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   10.21 + *
   10.22 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
   10.23 + */
   10.24 +
   10.25 +#include "yans/test.h"
   10.26 +
   10.27 +int main (int argc, char *argv[])
   10.28 +{
   10.29 +#ifdef RUN_SELF_TESTS
   10.30 +	yans::TestManager::enable_verbose ();
   10.31 +	yans::TestManager::run_tests ();
   10.32 +#endif /* RUN_SELF_TESTS */
   10.33 +
   10.34 +	return 0;
   10.35 +}