summaryrefslogtreecommitdiff
path: root/port.h
blob: 06a3aa5b913c72bc519ba83cdf87905f08b153e5 (plain) (blame)
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
#pragma once

#include <cassert>
#include <optional>
#include <utility>

#include "infra/sim.h"

namespace infra {
    template<typename T> struct port : public sim {
        std::optional<T> consumer_side;
        std::optional<T> producer_side;

        bool can_read() { return consumer_side.has_value(); }
        bool can_write() { return !producer_side.has_value(); }

        T read() {
            assert(can_read());
            auto x = std::move(*consumer_side);
            consumer_side.reset();
            return x;
        }

        const T & peek() {
            assert(can_read());
            return *consumer_side;
        }

        void discard() {
            consumer_side.reset();
        }

        void write(T &&x) {
            assert(can_write());
            producer_side = std::move(x);
        }

        void unclock() {
            if (!consumer_side && producer_side) {
                consumer_side = std::move(*producer_side);
                producer_side.reset();
            }
        }
    };
}