dev-arm: Set frequency ranges in OSC device tree nodes.
[gem5.git] / src / dev / pixelpump.hh
1 /*
2 * Copyright (c) 2015, 2017 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #ifndef __DEV_PIXELPUMP_HH__
39 #define __DEV_PIXELPUMP_HH__
40
41 #include "base/framebuffer.hh"
42 #include "sim/clocked_object.hh"
43
44 struct BasePixelPumpParams;
45
46 struct DisplayTimings : public Serializable
47 {
48 /**
49 * Create a display timing configuration struct
50 *
51 * @param width Width of the visible area of the screen.
52 * @param height Height of the visible area of the screen.
53 * @param hfp Horizontal front porch in pixel clocks.
54 * @param h_sync Horizontal sync in pixel clocks.
55 * @param hbp Horizontal back porch in pixel clocks.
56 * @param vfp Vertical front porch in scan lines.
57 * @param v_sync Vertical sync in scan lines.
58 * @param vbp Vertical back porch in scan lines.
59 */
60 DisplayTimings(unsigned width, unsigned height,
61 unsigned hbp, unsigned h_sync, unsigned hfp,
62 unsigned vbp, unsigned v_sync, unsigned vfp);
63
64 void serialize(CheckpointOut &cp) const override;
65 void unserialize(CheckpointIn &cp) override;
66
67 /** How many pixel clocks are required for one line? */
68 Cycles cyclesPerLine() const {
69 return Cycles(hSync + hBackPorch + width + hBackPorch);
70 }
71
72 /** How many pixel clocks are required for one frame? */
73 Cycles cyclesPerFrame() const {
74 return Cycles(cyclesPerLine() * linesPerFrame());
75 }
76
77 /** Calculate the first line of the vsync signal */
78 unsigned lineVSyncStart() const {
79 return 0;
80 }
81
82 /** Calculate the first line of the vertical back porch */
83 unsigned lineVBackPorchStart() const {
84 return lineVSyncStart() + vSync;
85 }
86
87 /** Calculate the first line of the visible region */
88 unsigned lineFirstVisible() const {
89 return lineVBackPorchStart() + vBackPorch;
90 }
91
92 /** Calculate the first line of the back porch */
93 unsigned lineFrontPorchStart() const {
94 return lineFirstVisible() + height;
95 }
96
97 /** Calculate the total number of lines in a frame */
98 unsigned linesPerFrame() const {
99 return lineFrontPorchStart() + vFrontPorch;
100 }
101
102 /** Display width in pixels */
103 unsigned width;
104 /** Display height in pixels */
105 unsigned height;
106
107 /** Horizontal back porch in pixels */
108 unsigned hBackPorch;
109 /** Horizontal front porch in pixels */
110 unsigned hFrontPorch;
111 /** Horizontal sync signal length in pixels */
112 unsigned hSync;
113
114 /** Vertical back porch in lines */
115 unsigned vBackPorch;
116 /** Vertical front porch in lines */
117 unsigned vFrontPorch;
118 /** Vertical sync signal in lines */
119 unsigned vSync;
120
121 static const DisplayTimings vga;
122 };
123
124 /**
125 * Timing generator for a pixel-based display.
126 *
127 * Pixels are ordered relative to the top left corner of the
128 * display. Scan lines appear in the following order:
129 * <ol>
130 * <li>Vertical Sync (starting at line 0)
131 * <li>Vertical back porch
132 * <li>Visible lines
133 * <li>Vertical front porch
134 * </ol>
135 *
136 * Pixel order within a scan line:
137 * <ol>
138 * <li>Horizontal Sync
139 * <li>Horizontal Back Porch
140 * <li>Visible pixels
141 * <li>Horizontal Front Porch
142 * </ol>
143 */
144 class BasePixelPump
145 : public EventManager, public Clocked,
146 public Serializable
147 {
148 public:
149 BasePixelPump(EventManager &em, ClockDomain &pxl_clk,
150 unsigned pixel_chunk);
151 virtual ~BasePixelPump();
152
153 void serialize(CheckpointOut &cp) const override;
154 void unserialize(CheckpointIn &cp) override;
155
156 public: // Public API
157 /** Update frame size using display timing */
158 void updateTimings(const DisplayTimings &timings);
159
160 /** Render an entire frame in KVM execution mode */
161 void renderFrame();
162
163 /** Starting pushing pixels in timing mode */
164 void start();
165
166 /** Immediately stop pushing pixels */
167 void stop();
168
169 /** Get a constant reference of the current display timings */
170 const DisplayTimings &timings() const { return _timings; }
171
172 /** Is the pixel pump active and refreshing the display? */
173 bool active() const { return evBeginLine.active(); }
174
175 /** Did a buffer underrun occur within this refresh interval? */
176 bool underrun() const { return _underrun; }
177
178 /** Is the current line within the visible range? */
179 bool visibleLine() const {
180 return line >= _timings.lineFirstVisible() &&
181 line < _timings.lineFrontPorchStart();
182 }
183
184 /** Current pixel position within the visible area */
185 unsigned posX() const { return _posX; }
186
187 /** Current pixel position within the visible area */
188 unsigned posY() const {
189 return visibleLine() ? line - _timings.lineFirstVisible() : 0;
190 }
191
192 /** Output frame buffer */
193 FrameBuffer fb;
194
195 protected: // Callbacks
196 /**
197 * Get the next pixel from the scan line buffer.
198 *
199 * @param p Output pixel value, undefined on underrun
200 * @return true on success, false on buffer underrun
201 */
202 virtual bool nextPixel(Pixel &p) = 0;
203
204 /** First pixel clock of the first VSync line. */
205 virtual void onVSyncBegin() {};
206
207 /**
208 * Callback on the first pixel of the line after the end VSync
209 * region (typically the first pixel of the vertical back porch).
210 */
211 virtual void onVSyncEnd() {};
212
213 /**
214 * Start of the HSync region.
215 *
216 * @note This is called even for scan lines outside of the visible
217 * region.
218 */
219 virtual void onHSyncBegin() {};
220
221 /**
222 * Start of the first pixel after the HSync region.
223 *
224 * @note This is called even for scan lines outside of the visible
225 * region.
226 */
227 virtual void onHSyncEnd() {};
228
229 /**
230 * Buffer underrun occurred on a frame.
231 *
232 * This method is called once if there is buffer underrun while
233 * refreshing the display. The underrun state is reset on the next
234 * refresh.
235 *
236 * @param x Coordinate within the visible region.
237 * @param y Coordinate within the visible region.
238 */
239 virtual void onUnderrun(unsigned x, unsigned y) {};
240
241 /** Finished displaying the visible region of a frame */
242 virtual void onFrameDone() {};
243
244 private: // Params
245 /** Maximum number of pixels to handle per render callback */
246 const unsigned pixelChunk;
247
248 private:
249 /**
250 * Callback helper class with suspend support.
251 *
252 * Unlike a normal EventWrapper, this class suspends an event on
253 * drain() and restarts it at drainResume(). The suspend operation
254 * stores the tick relative to curTick() and then deschedules the
255 * event. The resume operation schedules the event at curTick()
256 * plus the relative tick stored when the event was suspended.
257 */
258 class PixelEvent : public Event, public Drainable
259 {
260 typedef void (BasePixelPump::* CallbackType)();
261
262 public:
263 PixelEvent(const char *name, BasePixelPump *parent, CallbackType func);
264
265 DrainState drain() override;
266 void drainResume() override;
267
268 void serialize(CheckpointOut &cp) const override;
269 void unserialize(CheckpointIn &cp) override;
270
271 const std::string name() const override { return _name; }
272 void process() override {
273 (parent.*func)();
274 }
275
276 bool active() const { return scheduled() || suspended; }
277
278 private:
279 void suspend();
280 void resume();
281
282 const std::string _name;
283 BasePixelPump &parent;
284 const CallbackType func;
285
286 bool suspended;
287 Tick relativeTick;
288 };
289
290 void beginLine();
291 void renderPixels();
292
293 /** Fast and event-free line rendering function */
294 void renderLine();
295
296 /** Convenience vector when doing operations on all events */
297 std::vector<PixelEvent *> pixelEvents;
298
299 PixelEvent evVSyncBegin;
300 PixelEvent evVSyncEnd;
301 PixelEvent evHSyncBegin;
302 PixelEvent evHSyncEnd;
303 PixelEvent evBeginLine;
304 PixelEvent evRenderPixels;
305
306 DisplayTimings _timings;
307
308 /**
309 * Current line (including back porch, front porch, and vsync)
310 * within a frame.
311 */
312 unsigned line;
313 /** X-coordinate within the visible region of a frame */
314 unsigned _posX;
315
316 /** Did a buffer underrun occur within this refresh interval? */
317 bool _underrun;
318 };
319
320 #endif // __DEV_PIXELPUMP_HH__