1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
#include <utility>
#include "sim/sim.h"
#include "util/assert.h"
namespace sim {
void Scheduler::add_schedulable(Schedulable *schedulable)
{
unsorted_schedulables.emplace(schedulable);
sort_needed = true;
}
void Scheduler::remove_schedulable(Schedulable *schedulable)
{
unsorted_schedulables.erase(schedulable);
std::erase_if(constraints, [schedulable](const auto &item) { return item.first == schedulable || item.second == schedulable; });
sort_needed = true;
}
void Scheduler::constrain(Schedulable *prior, Schedulable *later)
{
ASSERT(unsorted_schedulables.count(prior), "Constraint prior is not associated with this Scheduler");
ASSERT(unsorted_schedulables.count(later), "Constraint later is not associated with this Scheduler");
constraints.emplace(later, prior);
sort_needed = true;
}
void Scheduler::topo_sort(std::set<Schedulable *> &live, std::set<Schedulable *> &waiting, Schedulable *candidate)
{
ASSERT(!live.count(candidate), "Dependency loop");
for (auto prereq = constraints.find(candidate); prereq != constraints.end() && prereq->first == candidate; ++prereq) {
if (prereq->second != candidate && waiting.count(prereq->second)) {
live.emplace(candidate);
topo_sort(live, waiting, prereq->second);
}
}
sorted_schedulables.emplace_back(candidate);
waiting.erase(candidate);
}
void Scheduler::sort()
{
sorted_schedulables.clear();
sorted_schedulables.reserve(unsorted_schedulables.size());
auto waiting = unsorted_schedulables;
while (!waiting.empty()) {
std::set<Schedulable *> live;
topo_sort(live, waiting, *waiting.begin());
}
ASSERT(sorted_schedulables.size() == unsorted_schedulables.size(), "Did not sort every schedulable");
sort_needed = false;
}
void Scheduler::clock()
{
if (sort_needed)
sort();
for (const auto &s : sorted_schedulables) {
current_schedulable = s;
s->clock();
}
current_schedulable = nullptr;
++now;
}
Schedulable::Schedulable(Scheduler &scheduler)
: scheduler(scheduler)
{
scheduler.add_schedulable(this);
}
Schedulable::~Schedulable()
{
scheduler.remove_schedulable(this);
}
std::uint64_t Schedulable::now()
{
return scheduler.now;
}
}
|