aboutsummaryrefslogtreecommitdiff
path: root/src/optical_output_port.h
blob: c0cd7ddbd638d93b30c0bb57f06fc6e9ecea5ced (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#pragma once

#include <cstdlib>
#include <deque>
#include <systemc.h>
#include <utility>
#include <vector>
#include <queue>
#include <map>

#include <optical_signal.h>
#include <pqueue.h>

using std::cout;
using std::endl;

using std::pair;
using std::vector;
using std::priority_queue;

enum OpticalOutputPortMode {
    PORT_MODE_MINVAL,
    EVENT_DRIVEN,
    SAMPLED_TIME,
    NO_DELAY,
    PORT_MODE_MAXVAL,

    // aliases
    TIME_DOMAIN      = EVENT_DRIVEN,
    FREQUENCY_DOMAIN = NO_DELAY,
    DEFAULT          = EVENT_DRIVEN,
    UNDEFINED        = PORT_MODE_MAXVAL,
};

string oopPortMode2str(OpticalOutputPortMode mode);

class OpticalOutputPortConfig {
public:
    OpticalOutputPortMode m_mode = OpticalOutputPortMode::DEFAULT;
    double m_abstol = 1e-8;
    double m_reltol = 1e-4;
    sc_time::value_type m_timestep_value = 1; // relative to systemc timestep

    OpticalOutputPortConfig() {}
};

class OpticalOutputPort : public sc_module {
public:
    typedef OpticalOutputPort this_type;
	typedef sc_port<sc_signal_out_if<OpticalSignal>> port_type;
	typedef pair<sc_time, OpticalSignal> pair_type;
    typedef PQueue<pair_type> queue_type;


// private:
public:
    port_type &m_port;
    queue_type m_queue;
    // queue_type m_queue_fd;
    // queue_type m_queue_td;
    sc_event_queue m_event_queue;
    // sc_event_queue m_event_queue_td;
    // sc_event_queue m_event_queue_fd;
    // OpticalSignal m_cur_val;
    // OpticalSignal m_cur_val_td;
    // OpticalSignal m_cur_val_fd;
    // OpticalSignal m_emitted_val;
    // OpticalSignal m_emitted_val_fd;

    std::map<uint32_t,OpticalSignal::field_type> m_desired_fields;
    std::map<uint32_t,OpticalSignal::field_type> m_emitted_fields;

    sc_time m_temporal_resolution;
    OpticalOutputPortMode m_mode;
    double m_reltol;
    double m_abstol;
    bool m_use_deltas = false;
    bool m_converger = false;
    bool m_skip_next_convergence_check = false;
    bool m_skip_convergence_check = false;

    std::shared_ptr<const OpticalOutputPortConfig> m_config;

    // void drop_all_events();
    void on_data_ready();
    void on_data_ready_fd();
    bool check_emit_by_abstol(const OpticalSignal::field_type &desired, const OpticalSignal::field_type &last);
    bool check_emit_by_reltol(const OpticalSignal::field_type &desired, const OpticalSignal::field_type &last);

    void applyConfig();
    virtual void start_of_simulation();
    sc_time snap_to_next_valid_time(const sc_time &t, const unsigned int resolution_multiplier=1);
    void delayedWriteEventDriven(const OpticalSignal &value, const sc_time &delay, const unsigned int resolution_multiplier=1);
    void delayedWriteSampledTime(const OpticalSignal &value, const sc_time &delay, const unsigned int resolution_multiplier=1);
    void immediateWriteFrequencyDomain(const OpticalSignal &value);

public:
    OpticalOutputPort(sc_module_name name, port_type &p);

    ~OpticalOutputPort() {}

    // Set config
    void setConfig(shared_ptr<OpticalOutputPortConfig> &config)
    {
        m_config = config;
    }
    const shared_ptr<const OpticalOutputPortConfig>& getConfig() const
    {
        return m_config;
    }

    void drop_queue()
    {
        if (sc_get_simulator_status() == SC_RUNNING)
        {
            cerr << "Cannot drop if simulation is running" << endl;
            exit(1);
        }
        m_event_queue.cancel_all();
        m_queue = queue_type();
    }

    void reset()
    {
        drop_queue();
        m_desired_fields.clear();
        m_emitted_fields.clear();
    }

    void swap_wavelengths(uint32_t wl1, uint32_t wl2)
    {
        drop_queue();

        // Create entries with 0 if they don't exist
        m_desired_fields.emplace(wl1, 0);
        m_desired_fields.emplace(wl2, 0);
        m_emitted_fields.emplace(wl1, 0);
        m_emitted_fields.emplace(wl2, 0);

        // Swap wl1 and wl2 entries
        swap(m_desired_fields.at(wl1), m_desired_fields.at(wl2));
        swap(m_emitted_fields.at(wl1), m_emitted_fields.at(wl2));
    }

    void delete_wavelength(uint32_t wl)
    {
        drop_queue();
        // Create entries with 0 if they don't exist
        m_desired_fields.erase(wl);
        m_emitted_fields.erase(wl);
    }

    // inline double current_err() const {
    //     double err_abs_power = abs(m_cur_val.power() - m_emitted_val.power());
    //     double err_abs_phase = abs(m_cur_val.phase() - m_emitted_val.phase());
    //     if (m_cur_val.power() > m_abstol)
    //         return max(err_abs_power, err_abs_phase);
    //     return err_abs_power;
    // }

    inline double current_err_fd() const {
        cerr << "Using deprecated function: " << __FUNCTION__ << endl;
        exit(1);
        // double err_abs_power = abs(m_cur_val_fd.power() - m_emitted_val_fd.power());
        // double err_abs_phase = abs(m_cur_val_fd.phase() - m_emitted_val_fd.phase());
        // if (m_cur_val_fd.power() >= m_abstol)
        //     return max(err_abs_power, err_abs_phase);
        // return err_abs_power;
        return 0;
    }

    inline bool isempty() const
    {
        return m_queue.empty();
    }

    void delayedWrite(const OpticalSignal &value, const sc_time &delay, const unsigned int resolution_multiplier=1);
};