OpenCores
URL https://opencores.org/ocsvn/openhmc/openhmc/trunk

Subversion Repositories openhmc

[/] [openhmc/] [trunk/] [openHMC/] [sim/] [UVC/] [hmc/] [sv/] [hmc_responder_driver.sv] - Blame information for rev 15

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 juko
/*
2
 *                              .--------------. .----------------. .------------.
3
 *                             | .------------. | .--------------. | .----------. |
4
 *                             | | ____  ____ | | | ____    ____ | | |   ______ | |
5
 *                             | ||_   ||   _|| | ||_   \  /   _|| | | .' ___  || |
6
 *       ___  _ __   ___ _ __  | |  | |__| |  | | |  |   \/   |  | | |/ .'   \_|| |
7
 *      / _ \| '_ \ / _ \ '_ \ | |  |  __  |  | | |  | |\  /| |  | | || |       | |
8
 *       (_) | |_) |  __/ | | || | _| |  | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
9
 *      \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
10
 *           | |               | |            | | |              | | |          | |
11
 *           |_|               | '------------' | '--------------' | '----------' |
12
 *                              '--------------' '----------------' '------------'
13
 *
14
 *  openHMC - An Open Source Hybrid Memory Cube Controller
15
 *  (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
16
 *  www.ziti.uni-heidelberg.de
17
 *  B6, 26
18
 *  68159 Mannheim
19
 *  Germany
20
 *
21
 *  Contact: openhmc@ziti.uni-heidelberg.de
22
 *  http://ra.ziti.uni-heidelberg.de/openhmc
23
 *
24
 *   This source file is free software: you can redistribute it and/or modify
25
 *   it under the terms of the GNU Lesser General Public License as published by
26
 *   the Free Software Foundation, either version 3 of the License, or
27
 *   (at your option) any later version.
28
 *
29
 *   This source file is distributed in the hope that it will be useful,
30
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32
 *   GNU Lesser General Public License for more details.
33
 *
34
 *   You should have received a copy of the GNU Lesser General Public License
35
 *   along with this source file.  If not, see .
36
 *
37
 *
38
 */
39
`ifndef HMC_RESPONDER_DRIVER_SV
40
`define HMC_RESPONDER_DRIVER_SV
41
 
42
class hmc_responder_driver#(parameter NUM_LANES=16) extends hmc_driver_base#(NUM_LANES);
43
        bit clear_error = 0;
44
 
45
        `uvm_component_param_utils(hmc_responder_driver#(.NUM_LANES(NUM_LANES)))
46
 
47
        function new(string name="hmc_responder_driver", uvm_component parent);
48
                super.new(name,parent);
49
                hmc_frp_port    = new("hmc_frp_port", this);
50
        endfunction : new
51
 
52
        function void build_phase(uvm_phase phase);
53
                super.build_phase(phase);
54
                start_clear_retry_event = new("start_retry_event");
55
                local_config = link_config.responder;
56
 
57
                if (!local_config.requester) begin
58
                tokens_to_send = link_config.hmc_tokens;
59
 
60
                `uvm_info(get_type_name(),$psprintf("initial_trets token_count = %0d", link_config.hmc_tokens), UVM_NONE)
61
                end else begin
62
                        tokens_to_send = link_config.rx_tokens;
63
 
64
                        `uvm_info(get_type_name(),$psprintf("initial_trets token_count = %0d", link_config.rx_tokens), UVM_NONE)
65
                end
66
                token_count_not_zero : assert (tokens_to_send > 0);
67
        endfunction : build_phase
68
 
69
        task run_phase(uvm_phase phase);
70
                super.run_phase(phase);
71
 
72
                forever begin
73
                        if(vif.P_RST_N !== 1) begin
74
                                next_state = RESET;
75
                        end
76
 
77
                        fork
78
                                forever begin
79
                                        if (next_state != state) begin
80
                                                `uvm_info(get_type_name(),$psprintf("in state %s", next_state.name()), UVM_HIGH)
81
                                        end
82
 
83
 
84
                                        last_state = state;
85
                                        state = next_state;
86
 
87
                                        case (state)
88
                                                RESET: reset();
89
                                                POWER_DOWN: power_down();
90
                                                INIT: init();
91
                                                PRBS: prbs();
92
                                                NULL_FLITS: null_flits();
93
                                                TS1: ts1();
94
                                                NULL_FLITS_2: null_flits_2();
95
                                                INITIAL_TRETS: initial_trets();
96
                                                LINK_UP: link_up();
97
                                                START_RETRY_INIT: start_retry_init();
98
                                                CLEAR_RETRY: clear_retry();
99
                                                SEND_RETRY_PACKETS: send_retry_packets();
100
                                        endcase
101
                                        clear_error = 0;
102
                                end
103
                                begin
104
                                        @(negedge vif.P_RST_N);
105
                                end
106
                                forever begin
107
                                        start_clear_retry_event.wait_ptrigger();
108
                                        start_clear_retry_event.reset(0);
109
                                        next_state = CLEAR_RETRY;
110
                                        `uvm_info(get_type_name(), "start retry event was triggered", UVM_HIGH)
111
                                        clear_error = 1;
112
                                end
113
                                begin
114
                                        time wait_time;
115
                                        @(negedge vif.RXPS);
116
                                        power_down_time_success : assert (std::randomize(wait_time) with { wait_time>0 && wait_time <= link_config.t_PST + 3*link_config.t_SS;});
117
                                        #wait_time;
118
                                        vif.TXPS = 0;
119
                                        link_down_time_success : assert (std::randomize(wait_time) with { wait_time>0 && wait_time <= link_config.t_SME;});
120
                                        #wait_time;
121
                                        next_state = POWER_DOWN;
122
                                end
123
                                clk_gen();
124
                        join_any;
125
                        disable fork;
126
                end
127
 
128
        endtask : run_phase
129
 
130
        task reset();
131
 
132
                vif.TXP = {NUM_LANES {1'bz}};
133
                vif.TXN = {NUM_LANES {1'bz}};
134
                vif.TXPS = 1'bz;
135
                vif.FERR_N = 1'bz;
136
 
137
                seq_num = 1;
138
                last_rrp = 0;
139
                init_continue = 0;
140
                can_continue = 0;
141
                retry_buffer.reset();
142
 
143
                //wait for reset signal
144
                @(posedge vif.P_RST_N);
145
                reset_timestamp = $time;
146
 
147
                next_state = INIT;
148
        endtask : reset
149
 
150
        task power_down();
151
                time wait_time;
152
 
153
                clear_lanes();
154
                vif.TXP = {NUM_LANES {1'bz}};
155
                vif.TXN = {NUM_LANES {1'bz}};
156
 
157
                recover_from_power_down = 1;
158
 
159
                @(posedge vif.RXPS)
160
                //-- wait some time < t_pst
161
                power_up_time_success : assert (std::randomize(wait_time) with { wait_time>0 && wait_time <= link_config.t_PST + 3*link_config.t_SS;});
162
                #wait_time;
163
                vif.TXPS = 1;
164
                //-- wait some time < t_sme
165
                link_up_time_success : assert (std::randomize(wait_time) with { wait_time>0 && wait_time <= link_config.t_SME;});
166
                #wait_time;
167
                next_state = PRBS;
168
 
169
        endtask : power_down
170
 
171
        task init();
172
 
173
                //wait for tINIT to pass
174
                while ($time < reset_timestamp + link_config.tINIT)
175
                        @(posedge vif.REFCLKP);
176
 
177
                can_continue = 1;
178
 
179
                // TODO: Think of the "right" place to do this.
180
                // The problem is that it should happen in the sideband.
181
                // In our case, the sideband is software-controlled, not part of the controller.
182
                set_init_continue();
183
                `uvm_info(get_type_name(),$psprintf("active = %0d retry prob = %0d", local_config.active, local_config.random_retry_probability), UVM_HIGH)
184
 
185
                //wait for init_continue to be set
186
                while (!init_continue)
187
                        @(posedge vif.REFCLKP);
188
 
189
                //Set TXPS high
190
                vif.TXPS = 1'b1;
191
 
192
                //@(posedge vif.REFCLKP);
193
 
194
                next_state = PRBS;
195
        endtask : init
196
 
197
        task prbs();
198
                int prbs_time;
199
 
200
                prbs_timestamp = $time;
201
 
202
                // send PRBS at least until Requester locks
203
                while (!(remote_status.current_state > PRBS))
204
                        for (int i=0; i < 4; i++)
205
                                drive_fit({NUM_LANES/2 {i[1:0]}});
206
 
207
                // Randomize PRBS length
208
                prbs_time_randomization_succeeds : assert (std::randomize(prbs_time) with {prbs_time > 0ns && prbs_time < link_config.tRESP1;});
209
                `uvm_info(get_type_name(),$psprintf("prbs_time = %0d (between %0d and %0d)", prbs_time, 0ns, link_config.tRESP1), UVM_HIGH)
210
 
211
                for (int i=0; i < prbs_time/link_config.bit_time; i++) begin
212
                        drive_fit({NUM_LANES/2 {i[1:0]}});
213
                end
214
 
215
                next_state = NULL_FLITS;
216
        endtask : prbs
217
 
218
        task null_flits();
219
                int null_time;
220
 
221
                null_timestamp = $time;
222
 
223
                reset_lfsr();
224
 
225
                //wait for Requester to send TS1
226
                while (!(remote_status.current_state >NULL_FLITS))
227
                        drive_fit({NUM_LANES {1'b0}});
228
 
229
                req_ts1_timestamp = $time;
230
 
231
                //wait at most tRESP2
232
                null_time_randomization_succeeds : assert (std::randomize(null_time) with {null_time > 0ns && null_time < link_config.tRESP2;});
233
                `uvm_info(get_type_name(),$psprintf("null time = %0d ", null_time), UVM_HIGH)
234
                for (int i=0; i
235
                        drive_fit({NUM_LANES {1'b0}});
236
                end
237
 
238
                next_state = TS1;
239
        endtask : null_flits
240
 
241
        task ts1();
242
                int ts1_fits = 0;
243
 
244
                // Save the timestamp
245
                ts1_timestamp = $time;
246
                `uvm_info(get_type_name(), $psprintf("Sending TS1 Sequences"),UVM_MEDIUM)
247
                //wait for Requester to send NULL FLITs
248
                while (!(remote_status.current_state>TS1))
249
                        send_ts1(256); // 16 fits per sequence number, 16 sequence numbers
250
 
251
                next_state = NULL_FLITS_2;
252
        endtask : ts1
253
 
254
        task null_flits_2();
255
                int null_flit_count;
256
 
257
                null_flit_count_randomization_succeeds : assert (std::randomize(null_flit_count) with {null_flit_count >= 32 && null_flit_count < 512;});
258
 
259
                //send NULL FLITs
260
                for (int i=0; i < null_flit_count; i++)
261
                        drive_flit(128'h0);
262
 
263
                next_state = INITIAL_TRETS;
264
        endtask : null_flits_2
265
 
266
        function void drive_lanes(input bit[NUM_LANES-1:0] new_value);
267
                int i;
268
 
269
                bit[NUM_LANES-1:0] lanes_reordered;
270
 
271
                if (local_config.reverse_lanes) begin
272
                        for (i = 0; i < local_config.width; i= i+1) begin
273
                                lanes_reordered[i] = new_value[local_config.width-i-1];
274
                        end
275
                end else begin
276
                        lanes_reordered = new_value;
277
                end
278
 
279
                for (i = 0; i < local_config.width; i= i+1) begin
280
                        bit set;
281
                        lane_queues[i].push_back(lanes_reordered[i]  ^ local_config.reverse_polarity[i]);
282
 
283
                        if (local_config.lane_delays[i] <= lane_queues[i].size()) begin
284
                                set = lane_queues[i].pop_front();
285
                                vif.TXP[i] = set;
286
                                vif.TXN[i] = ~set;
287
                        end
288
                end
289
        endfunction : drive_lanes
290
 
291
        task clear_lanes();
292
                //-- while lane_queues.size >0
293
                int i;
294
                bit empty = 1;
295
                while(empty) begin
296
                        empty =0;
297
                        @driver_clk;
298
                        for (i = 0; i < local_config.width; i= i+1) begin
299
                                        logic set;
300
                                if (lane_queues[i].size>0) begin
301
                                        empty = 1;
302
                                        set = lane_queues[i].pop_front();
303
                                        vif.TXP[i] = set;
304
                                        vif.TXN[i] = ~set;
305
                                end     else begin
306
                                        vif.TXP[i] = 1'bz;
307
                                        vif.TXN[i] = 1'bz;
308
                                end
309
                        end
310
                end
311
        endtask : clear_lanes
312
 
313
endclass : hmc_responder_driver
314
 
315
`endif // HMC_RESPONDER_DRIVER_SV
316
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.