summaryrefslogtreecommitdiff
path: root/sim/queue.h
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/queue.h
parentTrivial code reorg. (diff)
downloadissim-c72951a36d6cb9775dc1ecd9bc26bc13e796f10c.tar.xz
Dropping the async interface, and adding some real uarch.
Diffstat (limited to 'sim/queue.h')
-rw-r--r--sim/queue.h87
1 files changed, 87 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}