111012Sandreas.sandberg@arm.com/*
211897Ssudhanshu.jha@arm.com * Copyright (c) 2015, 2017 ARM Limited
311012Sandreas.sandberg@arm.com * All rights reserved
411012Sandreas.sandberg@arm.com *
511012Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
611012Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
711012Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
811012Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
911012Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
1011012Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
1111012Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
1211012Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
1311012Sandreas.sandberg@arm.com *
1411012Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
1511012Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
1611012Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
1711012Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
1811012Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1911012Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
2011012Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
2111012Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
2211012Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
2311012Sandreas.sandberg@arm.com * this software without specific prior written permission.
2411012Sandreas.sandberg@arm.com *
2511012Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2611012Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2711012Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2811012Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2911012Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3011012Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3111012Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3211012Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3311012Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3411012Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3511012Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3611012Sandreas.sandberg@arm.com *
3711012Sandreas.sandberg@arm.com * Authors: Andreas Sandberg
3811012Sandreas.sandberg@arm.com */
3911012Sandreas.sandberg@arm.com
4011012Sandreas.sandberg@arm.com#ifndef __DEV_PIXELPUMP_HH__
4111012Sandreas.sandberg@arm.com#define __DEV_PIXELPUMP_HH__
4211012Sandreas.sandberg@arm.com
4311012Sandreas.sandberg@arm.com#include "base/framebuffer.hh"
4411012Sandreas.sandberg@arm.com#include "sim/clocked_object.hh"
4511012Sandreas.sandberg@arm.com
4611012Sandreas.sandberg@arm.comstruct BasePixelPumpParams;
4711012Sandreas.sandberg@arm.com
4811012Sandreas.sandberg@arm.comstruct DisplayTimings : public Serializable
4911012Sandreas.sandberg@arm.com{
5011012Sandreas.sandberg@arm.com    /**
5111012Sandreas.sandberg@arm.com     * Create a display timing configuration struct
5211012Sandreas.sandberg@arm.com     *
5311012Sandreas.sandberg@arm.com     * @param width Width of the visible area of the screen.
5411012Sandreas.sandberg@arm.com     * @param height Height of the visible area of the screen.
5511012Sandreas.sandberg@arm.com     * @param hfp Horizontal front porch in pixel clocks.
5611012Sandreas.sandberg@arm.com     * @param h_sync Horizontal sync in pixel clocks.
5711012Sandreas.sandberg@arm.com     * @param hbp Horizontal back porch in pixel clocks.
5811012Sandreas.sandberg@arm.com     * @param vfp Vertical front porch in scan lines.
5911012Sandreas.sandberg@arm.com     * @param v_sync Vertical sync in scan lines.
6011012Sandreas.sandberg@arm.com     * @param vbp Vertical back porch in scan lines.
6111012Sandreas.sandberg@arm.com     */
6211012Sandreas.sandberg@arm.com    DisplayTimings(unsigned width, unsigned height,
6311012Sandreas.sandberg@arm.com                   unsigned hbp, unsigned h_sync, unsigned hfp,
6411012Sandreas.sandberg@arm.com                   unsigned vbp, unsigned v_sync, unsigned vfp);
6511012Sandreas.sandberg@arm.com
6611168Sandreas.hansson@arm.com    void serialize(CheckpointOut &cp) const override;
6711168Sandreas.hansson@arm.com    void unserialize(CheckpointIn &cp) override;
6811012Sandreas.sandberg@arm.com
6911012Sandreas.sandberg@arm.com    /** How many pixel clocks are required for one line? */
7011012Sandreas.sandberg@arm.com    Cycles cyclesPerLine() const {
7111012Sandreas.sandberg@arm.com        return Cycles(hSync + hBackPorch +  width + hBackPorch);
7211012Sandreas.sandberg@arm.com    }
7311012Sandreas.sandberg@arm.com
7411012Sandreas.sandberg@arm.com    /** How many pixel clocks are required for one frame? */
7511012Sandreas.sandberg@arm.com    Cycles cyclesPerFrame() const {
7611012Sandreas.sandberg@arm.com        return Cycles(cyclesPerLine() * linesPerFrame());
7711012Sandreas.sandberg@arm.com    }
7811012Sandreas.sandberg@arm.com
7911012Sandreas.sandberg@arm.com    /** Calculate the first line of the vsync signal */
8011012Sandreas.sandberg@arm.com    unsigned lineVSyncStart() const {
8111012Sandreas.sandberg@arm.com        return 0;
8211012Sandreas.sandberg@arm.com    }
8311012Sandreas.sandberg@arm.com
8411012Sandreas.sandberg@arm.com    /** Calculate the first line of the vertical back porch */
8511012Sandreas.sandberg@arm.com    unsigned lineVBackPorchStart() const {
8611012Sandreas.sandberg@arm.com        return lineVSyncStart() + vSync;
8711012Sandreas.sandberg@arm.com    }
8811012Sandreas.sandberg@arm.com
8911012Sandreas.sandberg@arm.com    /** Calculate the first line of the visible region */
9011012Sandreas.sandberg@arm.com    unsigned lineFirstVisible() const {
9111012Sandreas.sandberg@arm.com        return lineVBackPorchStart() + vBackPorch;
9211012Sandreas.sandberg@arm.com    }
9311012Sandreas.sandberg@arm.com
9411012Sandreas.sandberg@arm.com    /** Calculate the first line of the back porch */
9511012Sandreas.sandberg@arm.com    unsigned lineFrontPorchStart() const {
9611012Sandreas.sandberg@arm.com        return lineFirstVisible() + height;
9711012Sandreas.sandberg@arm.com    }
9811012Sandreas.sandberg@arm.com
9911012Sandreas.sandberg@arm.com    /** Calculate the total number of lines in a frame */
10011012Sandreas.sandberg@arm.com    unsigned linesPerFrame() const {
10111012Sandreas.sandberg@arm.com        return lineFrontPorchStart() + vFrontPorch;
10211012Sandreas.sandberg@arm.com    }
10311012Sandreas.sandberg@arm.com
10411012Sandreas.sandberg@arm.com    /** Display width in pixels */
10511012Sandreas.sandberg@arm.com    unsigned width;
10611012Sandreas.sandberg@arm.com    /** Display height in pixels */
10711012Sandreas.sandberg@arm.com    unsigned height;
10811012Sandreas.sandberg@arm.com
10911012Sandreas.sandberg@arm.com    /** Horizontal back porch in pixels */
11011012Sandreas.sandberg@arm.com    unsigned hBackPorch;
11111012Sandreas.sandberg@arm.com    /** Horizontal front porch in pixels */
11211012Sandreas.sandberg@arm.com    unsigned hFrontPorch;
11311012Sandreas.sandberg@arm.com    /** Horizontal sync signal length in pixels */
11411012Sandreas.sandberg@arm.com    unsigned hSync;
11511012Sandreas.sandberg@arm.com
11611012Sandreas.sandberg@arm.com    /** Vertical back porch in lines */
11711012Sandreas.sandberg@arm.com    unsigned vBackPorch;
11811012Sandreas.sandberg@arm.com    /** Vertical front porch in lines */
11911012Sandreas.sandberg@arm.com    unsigned vFrontPorch;
12011012Sandreas.sandberg@arm.com    /** Vertical sync signal in lines */
12111012Sandreas.sandberg@arm.com    unsigned vSync;
12211012Sandreas.sandberg@arm.com
12311012Sandreas.sandberg@arm.com    static const DisplayTimings vga;
12411012Sandreas.sandberg@arm.com};
12511012Sandreas.sandberg@arm.com
12611012Sandreas.sandberg@arm.com/**
12711012Sandreas.sandberg@arm.com * Timing generator for a pixel-based display.
12811012Sandreas.sandberg@arm.com *
12911012Sandreas.sandberg@arm.com * Pixels are ordered relative to the top left corner of the
13011012Sandreas.sandberg@arm.com * display. Scan lines appear in the following order:
13111012Sandreas.sandberg@arm.com * <ol>
13211012Sandreas.sandberg@arm.com *   <li>Vertical Sync (starting at line 0)
13311012Sandreas.sandberg@arm.com *   <li>Vertical back porch
13411012Sandreas.sandberg@arm.com *   <li>Visible lines
13511012Sandreas.sandberg@arm.com *   <li>Vertical front porch
13611012Sandreas.sandberg@arm.com * </ol>
13711012Sandreas.sandberg@arm.com *
13811012Sandreas.sandberg@arm.com * Pixel order within a scan line:
13911012Sandreas.sandberg@arm.com * <ol>
14011012Sandreas.sandberg@arm.com *   <li>Horizontal Sync
14111012Sandreas.sandberg@arm.com *   <li>Horizontal Back Porch
14211012Sandreas.sandberg@arm.com *   <li>Visible pixels
14311012Sandreas.sandberg@arm.com *   <li>Horizontal Front Porch
14411012Sandreas.sandberg@arm.com * </ol>
14511012Sandreas.sandberg@arm.com */
14611012Sandreas.sandberg@arm.comclass BasePixelPump
14711012Sandreas.sandberg@arm.com    : public EventManager, public Clocked,
14811012Sandreas.sandberg@arm.com      public Serializable
14911012Sandreas.sandberg@arm.com{
15011012Sandreas.sandberg@arm.com  public:
15111897Ssudhanshu.jha@arm.com    BasePixelPump(EventManager &em, ClockDomain &pxl_clk,
15211897Ssudhanshu.jha@arm.com                  unsigned pixel_chunk);
15311012Sandreas.sandberg@arm.com    virtual ~BasePixelPump();
15411012Sandreas.sandberg@arm.com
15511168Sandreas.hansson@arm.com    void serialize(CheckpointOut &cp) const override;
15611168Sandreas.hansson@arm.com    void unserialize(CheckpointIn &cp) override;
15711012Sandreas.sandberg@arm.com
15811012Sandreas.sandberg@arm.com  public: // Public API
15911897Ssudhanshu.jha@arm.com    /** Update frame size using display timing */
16011897Ssudhanshu.jha@arm.com    void updateTimings(const DisplayTimings &timings);
16111897Ssudhanshu.jha@arm.com
16211897Ssudhanshu.jha@arm.com    /** Render an entire frame in KVM execution mode */
16311897Ssudhanshu.jha@arm.com    void renderFrame();
16411897Ssudhanshu.jha@arm.com
16511897Ssudhanshu.jha@arm.com    /** Starting pushing pixels in timing mode */
16611897Ssudhanshu.jha@arm.com    void start();
16711012Sandreas.sandberg@arm.com
16811012Sandreas.sandberg@arm.com    /** Immediately stop pushing pixels */
16911012Sandreas.sandberg@arm.com    void stop();
17011012Sandreas.sandberg@arm.com
17111012Sandreas.sandberg@arm.com    /** Get a constant reference of the current display timings */
17211012Sandreas.sandberg@arm.com    const DisplayTimings &timings() const { return _timings; }
17311012Sandreas.sandberg@arm.com
17411012Sandreas.sandberg@arm.com    /** Is the pixel pump active and refreshing the display? */
17511012Sandreas.sandberg@arm.com    bool active() const { return evBeginLine.active(); }
17611012Sandreas.sandberg@arm.com
17711012Sandreas.sandberg@arm.com    /** Did a buffer underrun occur within this refresh interval? */
17811012Sandreas.sandberg@arm.com    bool underrun() const { return _underrun; }
17911012Sandreas.sandberg@arm.com
18011012Sandreas.sandberg@arm.com    /** Is the current line within the visible range? */
18111012Sandreas.sandberg@arm.com    bool visibleLine() const {
18211012Sandreas.sandberg@arm.com        return line >= _timings.lineFirstVisible() &&
18311012Sandreas.sandberg@arm.com            line < _timings.lineFrontPorchStart();
18411012Sandreas.sandberg@arm.com    }
18511012Sandreas.sandberg@arm.com
18611012Sandreas.sandberg@arm.com    /** Current pixel position within the visible area */
18711012Sandreas.sandberg@arm.com    unsigned posX() const { return _posX; }
18811012Sandreas.sandberg@arm.com
18911012Sandreas.sandberg@arm.com    /** Current pixel position within the visible area */
19011012Sandreas.sandberg@arm.com    unsigned posY() const {
19111012Sandreas.sandberg@arm.com        return visibleLine() ? line - _timings.lineFirstVisible() : 0;
19211012Sandreas.sandberg@arm.com    }
19311012Sandreas.sandberg@arm.com
19411012Sandreas.sandberg@arm.com    /** Output frame buffer */
19511012Sandreas.sandberg@arm.com    FrameBuffer fb;
19611012Sandreas.sandberg@arm.com
19711012Sandreas.sandberg@arm.com  protected: // Callbacks
19811012Sandreas.sandberg@arm.com    /**
19911012Sandreas.sandberg@arm.com     * Get the next pixel from the scan line buffer.
20011012Sandreas.sandberg@arm.com     *
20111012Sandreas.sandberg@arm.com     * @param p Output pixel value, undefined on underrun
20211012Sandreas.sandberg@arm.com     * @return true on success, false on buffer underrun
20311012Sandreas.sandberg@arm.com     */
20411012Sandreas.sandberg@arm.com    virtual bool nextPixel(Pixel &p) = 0;
20511012Sandreas.sandberg@arm.com
20611012Sandreas.sandberg@arm.com    /** First pixel clock of the first VSync line. */
20711012Sandreas.sandberg@arm.com    virtual void onVSyncBegin() {};
20811012Sandreas.sandberg@arm.com
20911012Sandreas.sandberg@arm.com    /**
21011012Sandreas.sandberg@arm.com     * Callback on the first pixel of the line after the end VSync
21111012Sandreas.sandberg@arm.com     * region (typically the first pixel of the vertical back porch).
21211012Sandreas.sandberg@arm.com     */
21311012Sandreas.sandberg@arm.com    virtual void onVSyncEnd() {};
21411012Sandreas.sandberg@arm.com
21511012Sandreas.sandberg@arm.com    /**
21611012Sandreas.sandberg@arm.com     * Start of the HSync region.
21711012Sandreas.sandberg@arm.com     *
21811012Sandreas.sandberg@arm.com     * @note This is called even for scan lines outside of the visible
21911012Sandreas.sandberg@arm.com     * region.
22011012Sandreas.sandberg@arm.com     */
22111012Sandreas.sandberg@arm.com    virtual void onHSyncBegin() {};
22211012Sandreas.sandberg@arm.com
22311012Sandreas.sandberg@arm.com    /**
22411012Sandreas.sandberg@arm.com     * Start of the first pixel after the HSync region.
22511012Sandreas.sandberg@arm.com     *
22611012Sandreas.sandberg@arm.com     * @note This is called even for scan lines outside of the visible
22711012Sandreas.sandberg@arm.com     * region.
22811012Sandreas.sandberg@arm.com     */
22911012Sandreas.sandberg@arm.com    virtual void onHSyncEnd() {};
23011012Sandreas.sandberg@arm.com
23111012Sandreas.sandberg@arm.com    /**
23211012Sandreas.sandberg@arm.com     * Buffer underrun occurred on a frame.
23311012Sandreas.sandberg@arm.com     *
23411012Sandreas.sandberg@arm.com     * This method is called once if there is buffer underrun while
23511012Sandreas.sandberg@arm.com     * refreshing the display. The underrun state is reset on the next
23611012Sandreas.sandberg@arm.com     * refresh.
23711012Sandreas.sandberg@arm.com     *
23811012Sandreas.sandberg@arm.com     * @param x Coordinate within the visible region.
23911012Sandreas.sandberg@arm.com     * @param y Coordinate within the visible region.
24011012Sandreas.sandberg@arm.com     */
24111012Sandreas.sandberg@arm.com    virtual void onUnderrun(unsigned x, unsigned y) {};
24211012Sandreas.sandberg@arm.com
24311012Sandreas.sandberg@arm.com    /** Finished displaying the visible region of a frame */
24411012Sandreas.sandberg@arm.com    virtual void onFrameDone() {};
24511012Sandreas.sandberg@arm.com
24611012Sandreas.sandberg@arm.com  private: // Params
24711012Sandreas.sandberg@arm.com    /** Maximum number of pixels to handle per render callback */
24811012Sandreas.sandberg@arm.com    const unsigned pixelChunk;
24911012Sandreas.sandberg@arm.com
25011012Sandreas.sandberg@arm.com  private:
25111012Sandreas.sandberg@arm.com    /**
25211012Sandreas.sandberg@arm.com     * Callback helper class with suspend support.
25311012Sandreas.sandberg@arm.com     *
25411012Sandreas.sandberg@arm.com     * Unlike a normal EventWrapper, this class suspends an event on
25511012Sandreas.sandberg@arm.com     * drain() and restarts it at drainResume(). The suspend operation
25611012Sandreas.sandberg@arm.com     * stores the tick relative to curTick() and then deschedules the
25711012Sandreas.sandberg@arm.com     * event. The resume operation schedules the event at curTick()
25811012Sandreas.sandberg@arm.com     * plus the relative tick stored when the event was suspended.
25911012Sandreas.sandberg@arm.com     */
26011012Sandreas.sandberg@arm.com    class PixelEvent : public Event, public Drainable
26111012Sandreas.sandberg@arm.com    {
26211012Sandreas.sandberg@arm.com        typedef void (BasePixelPump::* CallbackType)();
26311012Sandreas.sandberg@arm.com
26411012Sandreas.sandberg@arm.com      public:
26511012Sandreas.sandberg@arm.com        PixelEvent(const char *name, BasePixelPump *parent, CallbackType func);
26611012Sandreas.sandberg@arm.com
26711168Sandreas.hansson@arm.com        DrainState drain() override;
26811168Sandreas.hansson@arm.com        void drainResume() override;
26911012Sandreas.sandberg@arm.com
27011168Sandreas.hansson@arm.com        void serialize(CheckpointOut &cp) const override;
27111168Sandreas.hansson@arm.com        void unserialize(CheckpointIn &cp) override;
27211012Sandreas.sandberg@arm.com
27311168Sandreas.hansson@arm.com        const std::string name() const override { return _name; }
27411168Sandreas.hansson@arm.com        void process() override {
27511012Sandreas.sandberg@arm.com            (parent.*func)();
27611012Sandreas.sandberg@arm.com        }
27711012Sandreas.sandberg@arm.com
27811012Sandreas.sandberg@arm.com        bool active() const { return scheduled() || suspended; }
27911012Sandreas.sandberg@arm.com
28011012Sandreas.sandberg@arm.com      private:
28111012Sandreas.sandberg@arm.com        void suspend();
28211012Sandreas.sandberg@arm.com        void resume();
28311012Sandreas.sandberg@arm.com
28411012Sandreas.sandberg@arm.com        const std::string _name;
28511012Sandreas.sandberg@arm.com        BasePixelPump &parent;
28611012Sandreas.sandberg@arm.com        const CallbackType func;
28711012Sandreas.sandberg@arm.com
28811012Sandreas.sandberg@arm.com        bool suspended;
28911012Sandreas.sandberg@arm.com        Tick relativeTick;
29011012Sandreas.sandberg@arm.com    };
29111012Sandreas.sandberg@arm.com
29211012Sandreas.sandberg@arm.com    void beginLine();
29311012Sandreas.sandberg@arm.com    void renderPixels();
29411012Sandreas.sandberg@arm.com
29511897Ssudhanshu.jha@arm.com    /** Fast and event-free line rendering function */
29611897Ssudhanshu.jha@arm.com    void renderLine();
29711897Ssudhanshu.jha@arm.com
29811012Sandreas.sandberg@arm.com    /** Convenience vector when doing operations on all events */
29911012Sandreas.sandberg@arm.com    std::vector<PixelEvent *> pixelEvents;
30011012Sandreas.sandberg@arm.com
30111012Sandreas.sandberg@arm.com    PixelEvent evVSyncBegin;
30211012Sandreas.sandberg@arm.com    PixelEvent evVSyncEnd;
30311012Sandreas.sandberg@arm.com    PixelEvent evHSyncBegin;
30411012Sandreas.sandberg@arm.com    PixelEvent evHSyncEnd;
30511012Sandreas.sandberg@arm.com    PixelEvent evBeginLine;
30611012Sandreas.sandberg@arm.com    PixelEvent evRenderPixels;
30711012Sandreas.sandberg@arm.com
30811012Sandreas.sandberg@arm.com    DisplayTimings _timings;
30911012Sandreas.sandberg@arm.com
31011012Sandreas.sandberg@arm.com    /**
31111012Sandreas.sandberg@arm.com     * Current line (including back porch, front porch, and vsync)
31211012Sandreas.sandberg@arm.com     * within a frame.
31311012Sandreas.sandberg@arm.com     */
31411012Sandreas.sandberg@arm.com    unsigned line;
31511012Sandreas.sandberg@arm.com    /** X-coordinate within the visible region of a frame */
31611012Sandreas.sandberg@arm.com    unsigned _posX;
31711012Sandreas.sandberg@arm.com
31811012Sandreas.sandberg@arm.com    /** Did a buffer underrun occur within this refresh interval? */
31911012Sandreas.sandberg@arm.com    bool _underrun;
32011012Sandreas.sandberg@arm.com};
32111012Sandreas.sandberg@arm.com
32211012Sandreas.sandberg@arm.com#endif // __DEV_PIXELPUMP_HH__
323