Newer
Older
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#ifndef ASIC_SIMULATION_OPERATION_H
#define ASIC_SIMULATION_OPERATION_H
#include "../number.h"
#include "../span.h"
#include <cstddef>
#include <cstdint>
#include <fmt/format.h>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
namespace asic {
class operation;
class signal_source;
using result_key = std::string;
using result_map = std::unordered_map<result_key, std::optional<number>>;
using delay_map = std::unordered_map<result_key, number>;
using delay_queue = std::vector<std::pair<result_key, signal_source const*>>;
struct evaluation_context final {
result_map* results;
delay_map* delays;
delay_queue* deferred_delays;
std::optional<std::size_t> bits_override;
bool truncate;
};
class signal_source final {
public:
signal_source() noexcept = default;
signal_source(std::shared_ptr<const operation> op, std::size_t index, std::optional<std::size_t> bits);
[[nodiscard]] explicit operator bool() const noexcept;
[[nodiscard]] std::optional<number> current_output(delay_map const& delays) const;
[[nodiscard]] number evaluate_output(evaluation_context const& context) const;
[[nodiscard]] std::optional<std::size_t> bits() const noexcept;
private:
std::shared_ptr<const operation> m_operation;
std::size_t m_index = 0;
std::optional<std::size_t> m_bits;
};
class operation {
public:
virtual ~operation() = default;
[[nodiscard]] virtual std::size_t output_count() const noexcept = 0;
[[nodiscard]] virtual std::optional<number> current_output(std::size_t index, delay_map const& delays) const = 0;
[[nodiscard]] virtual number evaluate_output(std::size_t index, evaluation_context const& context) const = 0;
};
class abstract_operation : public operation {
public:
explicit abstract_operation(result_key key);
virtual ~abstract_operation() = default;
[[nodiscard]] std::optional<number> current_output(std::size_t, delay_map const&) const override;
[[nodiscard]] number evaluate_output(std::size_t index, evaluation_context const& context) const override;
protected:
[[nodiscard]] virtual number evaluate_output_impl(std::size_t index, evaluation_context const& context) const = 0;
[[nodiscard]] virtual number truncate_input(std::size_t index, number value, std::size_t bits) const;
[[nodiscard]] result_key const& key_base() const;
[[nodiscard]] result_key key_of_output(std::size_t index) const;
private:
result_key m_key;
};
class unary_operation : public abstract_operation {
public:
explicit unary_operation(result_key key);
virtual ~unary_operation() = default;
void connect(signal_source in);
protected:
[[nodiscard]] bool connected() const noexcept;
[[nodiscard]] signal_source const& input() const noexcept;
[[nodiscard]] number evaluate_input(evaluation_context const& context) const;
private:
signal_source m_in;
};
class binary_operation : public abstract_operation {
public:
explicit binary_operation(result_key key);
virtual ~binary_operation() = default;
void connect(signal_source lhs, signal_source rhs);
protected:
[[nodiscard]] signal_source const& lhs() const noexcept;
[[nodiscard]] signal_source const& rhs() const noexcept;
[[nodiscard]] number evaluate_lhs(evaluation_context const& context) const;
[[nodiscard]] number evaluate_rhs(evaluation_context const& context) const;
private:
signal_source m_lhs;
signal_source m_rhs;
};
class nary_operation : public abstract_operation {
public:
explicit nary_operation(result_key key);
virtual ~nary_operation() = default;
void connect(std::vector<signal_source> inputs);
protected:
[[nodiscard]] span<signal_source const> inputs() const noexcept;
[[nodiscard]] std::vector<number> evaluate_inputs(evaluation_context const& context) const;
private:
std::vector<signal_source> m_inputs;
};
} // namespace asic
#endif // ASIC_SIMULATION_OPERATION_H