simulavr  1.1.0
systemclock.cpp
Go to the documentation of this file.
1 /*
2  ****************************************************************************
3  *
4  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
5  * Copyright (C) 2001, 2002, 2003 Klaus Rudolph
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  ****************************************************************************
22  *
23  * $Id$
24  */
25 
26 #include "systemclocktypes.h"
27 #include "systemclock.h"
28 #include "simulationmember.h"
29 #include "helper.h"
30 #include "application.h"
31 #include "avrdevice.h"
32 #include "avrerror.h"
33 
34 #include "signal.h"
35 #include <assert.h>
36 
37 using namespace std;
38 
39 template<typename Key, typename Value>
41 {
42  this->reserve(10); // vector would free&malloc when we keep inserting and removing only 1 element.
43 }
44 
45 template<typename Key, typename Value>
47 {
48  assert(!this->empty());
49  Key k = this->back().first;
50  Value v = this->back().second;
51  RemoveMinimumAndInsert(k, v);
52  this->pop_back();
53 }
54 
55 template<typename Key, typename Value>
57 {
58  for(unsigned i = 0; i < this->size(); i++)
59  {
60  std::pair<Key,Value> item = (*this)[i];
61  if(item.second == v)
62  return true;
63  }
64  return false;
65 }
66 
67 template<typename Key, typename Value>
68 void MinHeap<Key, Value>::InsertInternal(Key k, Value v, unsigned pos)
69 {
70  for(unsigned i = pos;;) {
71  unsigned parent = i/2;
72  if(parent == 0 || (*this)[parent-1].first <= k) {
73  (*this)[i-1].first = k;
74  (*this)[i-1].second = v;
75  return;
76  }
77  Key k_temp = (*this)[parent-1].first;
78  Value v_temp = (*this)[parent-1].second;
79  (*this)[i-1].first = k_temp;
80  (*this)[i-1].second = v_temp;
81  i = parent;
82  }
83 }
84 
85 template<typename Key, typename Value>
87 {
88  assert(pos < this->size());
89  unsigned i = pos + 1;
90  for(;;) {
91  unsigned left = 2*i;
92  unsigned right = 2*i + 1;
93  unsigned smallest = i;
94  if(left-1 < this->size() && (*this)[left-1].first < k)
95  smallest = left;
96  if(right-1 < this->size() && (*this)[right-1].first < k && (*this)[right-1].first < (*this)[left-1].first)
97  smallest = right;
98  if(smallest == i) {
99  (*this)[smallest-1].first = k;
100  (*this)[smallest-1].second = v;
101  return;
102  }
103  Key k_temp = (*this)[smallest-1].first;
104  Value v_temp = (*this)[smallest-1].second;
105  (*this)[i-1].first = k_temp;
106  (*this)[i-1].second = v_temp;
107  i = smallest;
108  }
109 }
110 
112  static int no = 0;
113  currentTime = 0;
114  no++;
115  if(no > 1)
116  avr_error("Crazy problem: Second instance of SystemClock created!");
117 }
118 
121  for(mi = syncMembers.begin(); mi != syncMembers.end(); mi++)
122  {
123  AvrDevice* core = dynamic_cast<AvrDevice*>( mi->second );
124  if(core != NULL)
125  core->trace_on = trace_on;
126  }
127 }
128 
130  syncMembers.Insert(currentTime, dev);
131 }
132 
134  asyncMembers.push_back(dev);
135 }
136 
137 volatile bool breakMessage = false;
138 
139 int SystemClock::Step(bool &untilCoreStepFinished) {
140  // 0-> return also if cpu in waitstate
141  // 1-> return if cpu is really finished
142  int res = 0; // returns the state from a core step. Needed by gdb-server to
143  // watch for breakpoints
144 
145  static vector<SimulationMember*>::iterator ami;
146  static vector<SimulationMember*>::iterator amiEnd;
147 
148  if(syncMembers.begin() != syncMembers.end()) {
149  // take simulation member and current simulation time from time table
150  SimulationMember * core = syncMembers.begin()->second;
151  currentTime = syncMembers.begin()->first;
152  SystemClockOffset nextStepIn_ns = -1;
153 
154  syncMembers.RemoveMinimum();
155 
156  // do a step on simulation member
157  int rc = core->Step(untilCoreStepFinished, &nextStepIn_ns);
158  if (rc)
159  res = rc;
160 
161  if(nextStepIn_ns == 0) { // insert the next step behind the following!
162  nextStepIn_ns = 1 + (syncMembers.IsEmpty() ? currentTime : syncMembers.front().first);
163  } else if(nextStepIn_ns > 0)
164  nextStepIn_ns += currentTime;
165  // if nextStepIn_ns is < 0, it means, that this simulation member will not
166  // be called anymore!
167 
168  if(nextStepIn_ns > 0)
169  syncMembers.Insert(nextStepIn_ns, core);
170 
171  // handle async simulation members
172  amiEnd = asyncMembers.end();
173  for(ami = asyncMembers.begin(); ami != amiEnd; ami++) {
174  bool untilCoreStepFinished = false;
175  (*ami)->Step(untilCoreStepFinished, 0);
176  }
177  }
178 
179  // honour the stop command
180  if (breakMessage)
181  return 1;
182 
183  return res;
184 }
185 
187 
188  for(unsigned i = 0; i < syncMembers.size(); i++) {
189  if(syncMembers[i].second == sm) {
190  syncMembers.RemoveAtPositionAndInsert(newTime+currentTime+1, sm, i);
191  return;
192  }
193  }
194 
195  syncMembers.Insert(newTime+currentTime+1, sm);
196 }
197 
198 void OnBreak(int s) {
199  signal(SIGINT, SIG_DFL);
200  signal(SIGTERM, SIG_DFL);
201  breakMessage = true;
202 }
203 
205  breakMessage = true;
206 }
207 
209  breakMessage = false;
210  asyncMembers.clear();
211  syncMembers.clear();
212  currentTime = 0;
213 }
214 
216  long steps = 0;
217 
218  breakMessage = false; // if we run a second loop, clear break before entering loop
219 
220  signal(SIGINT, OnBreak);
221  signal(SIGTERM, OnBreak);
222 
223  while(breakMessage == false) {
224  steps++;
225  bool untilCoreStepFinished = false;
226  Step(untilCoreStepFinished);
227  }
228 
229  return steps;
230 }
231 
233  long steps = 0;
234 
235  breakMessage = false; // if we run a second loop, clear break before entering loop
236 
237  signal(SIGINT, OnBreak);
238  signal(SIGTERM, OnBreak);
239 
240  while((breakMessage== false) &&
241  (SystemClock::Instance().GetCurrentTime() < maxRunTime)) {
242  steps++;
243  bool untilCoreStepFinished = false;
244  if (Step(untilCoreStepFinished))
245  break;
246  }
247 
248  return steps;
249 }
250 
252  long steps = 0;
253  bool untilCoreStepFinished;
254 
255  breakMessage = false; // if we run a second loop, clear break before entering loop
256 
257  signal(SIGINT, OnBreak);
258  signal(SIGTERM, OnBreak);
259 
260  timeRange += SystemClock::Instance().GetCurrentTime();
261  while((breakMessage == false) && (SystemClock::Instance().GetCurrentTime() < timeRange)) {
262  untilCoreStepFinished = false;
263  if (Step(untilCoreStepFinished))
264  break;
265  steps++;
266  }
267 
268  return steps;
269 }
270 
272  static SystemClock obj;
273  return obj;
274 }
void Add(SimulationMember *dev)
Add a simulation member (normally a device)
Basic AVR device, contains the core functionality.
Definition: avrdevice.h:66
SystemClockOffset GetCurrentTime() const
Returns the current simulation time.
Definition: systemclock.h:95
int Step(bool &untilCoreStepFinished)
Process one simulation step.
long Run(SystemClockOffset maxRunTime)
Run simulation till given time is arrived or signal is cached.
void OnBreak(int s)
STL namespace.
bool ContainsValue(Value v) const
Definition: systemclock.cpp:56
void ResetClock(void)
Resets the simulation time and clears table for simulation members and async simulation members...
long Endless()
Run simulation endless till SIGINT or SIGTERM signal, return the number of CPU cycles.
long RunTimeRange(SystemClockOffset timeRange)
Like Run method, but stops on breakpoint or after given time offset.
#define avr_error(...)
Definition: avrerror.h:135
void AddAsyncMember(SimulationMember *dev)
Add a async simulation member, this will be called every simulation step.
static SystemClock & Instance()
Returns the central SystemClock instance for the application.
long long SystemClockOffset
void Stop()
Stop Run/Endless or Step asynchronously.
void InsertInternal(Key k, Value v, unsigned pos)
Definition: systemclock.cpp:68
SystemClock()
Do not this constructor from application code!
volatile bool breakMessage
Class to store and manage the central simulation time.
Definition: systemclock.h:82
void SetTraceModeForAllMembers(int trace_on)
Switches trace mode for all current found simulation members.
int trace_on
Definition: avrdevice.h:90
virtual int Step(bool &trueHwStep, SystemClockOffset *timeToNextStepIn_ns=0)=0
Return nonzero if a breakpoint was hit.
void RemoveMinimum()
Definition: systemclock.cpp:46
void RemoveAtPositionAndInsertInternal(Key k, Value v, unsigned pos)
Definition: systemclock.cpp:86
void Reschedule(SimulationMember *sm, SystemClockOffset newTime)
Moves the given simulation member to a new place in time table.