summaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
authorJulian Blake Kongslie2022-07-02 13:45:09 -0700
committerJulian Blake Kongslie2022-07-02 13:45:09 -0700
commitc72951a36d6cb9775dc1ecd9bc26bc13e796f10c (patch)
tree5a8fe196beba5c7c674d1b3d627c9a0beac849f5 /sim
parentTrivial code reorg. (diff)
downloadissim-c72951a36d6cb9775dc1ecd9bc26bc13e796f10c.tar.xz
Dropping the async interface, and adding some real uarch.
Diffstat (limited to '')
-rw-r--r--sim/queue.h87
-rw-r--r--sim/sim.cpp83
-rw-r--r--sim/sim.d1
-rw-r--r--sim/sim.h44
4 files changed, 215 insertions, 0 deletions
diff --git a/sim/queue.h b/sim/queue.h
new file mode 100644
index 0000000..890beb6
--- /dev/null
+++ b/sim/queue.h
@@ -0,0 +1,87 @@
1#pragma once
2
3#include <cstdint>
4#include <iterator> // IWYU pragma: keep
5#include <map>
6#include <set>
7
8#include "sim/sim.h"
9#include "util/assert.h"
10
11namespace sim {
12
13 template<typename Element> struct Queue {
14 Scheduler &scheduler;
15
16 Schedulable *reader = nullptr;
17 std::set<Schedulable *> writers;
18
19 unsigned int min_latency;
20
21 std::multimap<std::uint64_t, Element> waiting;
22
23 Queue(Scheduler &scheduler, unsigned int min_latency)
24 : scheduler(scheduler)
25 , min_latency(min_latency)
26 { }
27
28 void add_reader(Schedulable *x)
29 {
30 ASSERT(&x->scheduler == &scheduler, "Reader associated with incorrect Scheduler");
31 ASSERT(!reader, "Already have a reader");
32 reader = x;
33 if (min_latency == 0) {
34 for (const auto &w : writers)
35 scheduler.constrain(w, reader);
36 }
37 }
38
39 void add_writer(Schedulable *x)
40 {
41 ASSERT(&x->scheduler == &scheduler, "Writer associated with incorrect Scheduler");
42 writers.emplace(x);
43 if (min_latency == 0 && reader)
44 scheduler.constrain(x, reader);
45 }
46
47 void write(Element &&x)
48 {
49 write(std::move(x), min_latency);
50 }
51
52 void write(Element &&x, unsigned int latency)
53 {
54 ASSERT(latency >= min_latency, "Latency too low");
55 ASSERT(!scheduler.current_schedulable || writers.count(scheduler.current_schedulable), "Write lacks permission");
56 waiting.emplace(scheduler.now + min_latency, std::move(x));
57 }
58
59 unsigned int available()
60 {
61 ASSERT(!scheduler.current_schedulable || reader == scheduler.current_schedulable, "Read lacks permission");
62 unsigned int c = 0;
63 for (auto x = waiting.begin(); x != waiting.end() && x->first <= scheduler.now; ++x)
64 ++c;
65 return c;
66 }
67
68 Element &peek(unsigned int i=0)
69 {
70 ASSERT(i < available(), "Peek past available elements");
71 auto x = waiting.begin();
72 std::advance(x, i);
73 return x->second;
74 }
75
76 Element read(unsigned int i=0)
77 {
78 ASSERT(i < available(), "Read past available elements");
79 auto x = waiting.begin();
80 std::advance(x, i);
81 Element e{std::move(x->second)};
82 waiting.erase(x);
83 return e;
84 }
85 };
86
87}
diff --git a/sim/sim.cpp b/sim/sim.cpp
new file mode 100644
index 0000000..e8f84ee
--- /dev/null
+++ b/sim/sim.cpp
@@ -0,0 +1,83 @@
1#include <utility>
2
3#include "sim/sim.h"
4#include "util/assert.h"
5
6namespace sim {
7
8 void Scheduler::add_schedulable(Schedulable *schedulable)
9 {
10 unsorted_schedulables.emplace(schedulable);
11 sort_needed = true;
12 }
13
14 void Scheduler::remove_schedulable(Schedulable *schedulable)
15 {
16 unsorted_schedulables.erase(schedulable);
17 std::erase_if(constraints, [schedulable](const auto &item) { return item.first == schedulable || item.second == schedulable; });
18 sort_needed = true;
19 }
20
21 void Scheduler::constrain(Schedulable *prior, Schedulable *later)
22 {
23 ASSERT(unsorted_schedulables.count(prior), "Constraint prior is not associated with this Scheduler");
24 ASSERT(unsorted_schedulables.count(later), "Constraint later is not associated with this Scheduler");
25 constraints.emplace(later, prior);
26 sort_needed = true;
27 }
28
29 void Scheduler::topo_sort(std::set<Schedulable *> &live, std::set<Schedulable *> &waiting, Schedulable *candidate)
30 {
31 ASSERT(!live.count(candidate), "Dependency loop");
32 for (auto prereq = constraints.find(candidate); prereq != constraints.end() && prereq->first == candidate; ++prereq) {
33 if (prereq->second != candidate && waiting.count(prereq->second)) {
34 live.emplace(candidate);
35 topo_sort(live, waiting, prereq->second);
36 }
37 }
38 sorted_schedulables.emplace_back(candidate);
39 waiting.erase(candidate);
40 }
41
42 void Scheduler::sort()
43 {
44 sorted_schedulables.clear();
45 sorted_schedulables.reserve(unsorted_schedulables.size());
46 auto waiting = unsorted_schedulables;
47 while (!waiting.empty()) {
48 std::set<Schedulable *> live;
49 topo_sort(live, waiting, *waiting.begin());
50 }
51 ASSERT(sorted_schedulables.size() == unsorted_schedulables.size(), "Did not sort every schedulable");
52 sort_needed = false;
53 }
54
55 void Scheduler::clock()
56 {
57 if (sort_needed)
58 sort();
59 for (const auto &s : sorted_schedulables) {
60 current_schedulable = s;
61 s->clock();
62 }
63 current_schedulable = nullptr;
64 ++now;
65 }
66
67 Schedulable::Schedulable(Scheduler &scheduler)
68 : scheduler(scheduler)
69 {
70 scheduler.add_schedulable(this);
71 }
72
73 Schedulable::~Schedulable()
74 {
75 scheduler.remove_schedulable(this);
76 }
77
78 std::uint64_t Schedulable::now()
79 {
80 return scheduler.now;
81 }
82
83}
diff --git a/sim/sim.d b/sim/sim.d
new file mode 100644
index 0000000..d8953fb
--- /dev/null
+++ b/sim/sim.d
@@ -0,0 +1 @@
sim_SODEPS += build/libutil.so
diff --git a/sim/sim.h b/sim/sim.h
new file mode 100644
index 0000000..399832a
--- /dev/null
+++ b/sim/sim.h
@@ -0,0 +1,44 @@
1#pragma once
2
3#include <cstdint>
4#include <map>
5#include <set>
6#include <vector>
7
8namespace sim {
9
10 struct Schedulable;
11
12 struct Scheduler {
13 std::set<Schedulable *> unsorted_schedulables;
14 std::vector<Schedulable *> sorted_schedulables;
15 bool sort_needed = false;
16
17 std::multimap<Schedulable *, Schedulable *> constraints;
18
19 Schedulable *current_schedulable = nullptr;
20 std::uint64_t now = 0;
21
22 void add_schedulable(Schedulable *schedulable);
23 void remove_schedulable(Schedulable *schedulable);
24
25 void constrain(Schedulable *prior, Schedulable *later);
26
27 void topo_sort(std::set<Schedulable *> &live, std::set<Schedulable *> &waiting, Schedulable *candidate);
28 void sort();
29
30 void clock();
31 };
32
33 struct Schedulable {
34 Scheduler &scheduler;
35
36 Schedulable(Scheduler &scheduler);
37 virtual ~Schedulable();
38
39 virtual void clock() = 0;
40
41 std::uint64_t now();
42 };
43
44}