hdlcd.cc revision 10840:48039363f67a
1955SN/A/*
2955SN/A * Copyright (c) 2010-2013, 2015 ARM Limited
31762SN/A * All rights reserved
4955SN/A *
5955SN/A * The license below extends only to copyright in the software and shall
6955SN/A * not be construed as granting a license to any other intellectual
7955SN/A * property including but not limited to intellectual property relating
8955SN/A * to a hardware implementation of the functionality of the software
9955SN/A * licensed hereunder.  You may use the software subject to the license
10955SN/A * terms below provided that you ensure that this notice is replicated
11955SN/A * unmodified and in its entirety in all distributions of the software,
12955SN/A * modified or unmodified, in source code or in binary form.
13955SN/A *
14955SN/A * Redistribution and use in source and binary forms, with or without
15955SN/A * modification, are permitted provided that the following conditions are
16955SN/A * met: redistributions of source code must retain the above copyright
17955SN/A * notice, this list of conditions and the following disclaimer;
18955SN/A * redistributions in binary form must reproduce the above copyright
19955SN/A * notice, this list of conditions and the following disclaimer in the
20955SN/A * documentation and/or other materials provided with the distribution;
21955SN/A * neither the name of the copyright holders nor the names of its
22955SN/A * contributors may be used to endorse or promote products derived from
23955SN/A * this software without specific prior written permission.
24955SN/A *
25955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
352632Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
362632Sstever@eecs.umich.edu *
372632Sstever@eecs.umich.edu * Authors: Chris Emmons
382632Sstever@eecs.umich.edu */
39955SN/A
402632Sstever@eecs.umich.edu#include "dev/arm/hdlcd.hh"
412632Sstever@eecs.umich.edu
422761Sstever@eecs.umich.edu#include "base/vnc/vncinput.hh"
432632Sstever@eecs.umich.edu#include "base/output.hh"
442632Sstever@eecs.umich.edu#include "base/trace.hh"
452632Sstever@eecs.umich.edu#include "debug/HDLcd.hh"
462761Sstever@eecs.umich.edu#include "debug/Uart.hh"
472761Sstever@eecs.umich.edu#include "dev/arm/amba_device.hh"
482761Sstever@eecs.umich.edu#include "dev/arm/base_gic.hh"
492632Sstever@eecs.umich.edu#include "mem/packet.hh"
502632Sstever@eecs.umich.edu#include "mem/packet_access.hh"
512761Sstever@eecs.umich.edu#include "sim/system.hh"
522761Sstever@eecs.umich.edu
532761Sstever@eecs.umich.eduusing std::vector;
542761Sstever@eecs.umich.edu
552761Sstever@eecs.umich.edu
562632Sstever@eecs.umich.edu// initialize hdlcd registers
572632Sstever@eecs.umich.eduHDLcd::HDLcd(const Params *p)
582632Sstever@eecs.umich.edu    : AmbaDmaDevice(p), version(VERSION_RESETV),
592632Sstever@eecs.umich.edu      int_rawstat(0), int_clear(0), int_mask(0), int_status(0),
602632Sstever@eecs.umich.edu      fb_base(0), fb_line_length(0), fb_line_count(0), fb_line_pitch(0),
612632Sstever@eecs.umich.edu      bus_options(BUS_OPTIONS_RESETV),
622632Sstever@eecs.umich.edu      v_sync(0), v_back_porch(0), v_data(0), v_front_porch(0),
63955SN/A      h_sync(0), h_back_porch(0), h_data(0), h_front_porch(0),
64955SN/A      polarities(0), command(0), pixel_format(0),
65955SN/A      red_select(0), green_select(0), blue_select(0),
66955SN/A      pixelClock(p->pixel_clock),
67955SN/A      fb(0, 0), vnc(p->vnc), bmp(&fb), pic(NULL),
685396Ssaidi@eecs.umich.edu      frameReadStartTime(0),
694202Sbinkertn@umich.edu      dmaStartAddr(0), dmaCurAddr(0), dmaMaxAddr(0), dmaPendingNum(0),
705342Sstever@gmail.com      frameUnderrun(false), pixelBufferSize(0),
71955SN/A      pixelIndex(0), doUpdateParams(false), frameUnderway(false),
725273Sstever@gmail.com      dmaBytesInFlight(0),
735273Sstever@gmail.com      startFrameEvent(this), endFrameEvent(this), renderPixelEvent(this),
742656Sstever@eecs.umich.edu      fillPixelBufferEvent(this), intEvent(this),
752656Sstever@eecs.umich.edu      dmaDoneEventAll(MAX_OUTSTANDING_DMA_REQ_CAPACITY, this),
762656Sstever@eecs.umich.edu      dmaDoneEventFree(MAX_OUTSTANDING_DMA_REQ_CAPACITY),
772656Sstever@eecs.umich.edu      enableCapture(p->enable_capture),
782656Sstever@eecs.umich.edu      workaround_swap_rb(p->workaround_swap_rb)
792656Sstever@eecs.umich.edu{
802656Sstever@eecs.umich.edu    pioSize = 0xFFFF;
812653Sstever@eecs.umich.edu
825227Ssaidi@eecs.umich.edu    for (int i = 0; i < MAX_OUTSTANDING_DMA_REQ_CAPACITY; ++i)
835227Ssaidi@eecs.umich.edu        dmaDoneEventFree[i] = &dmaDoneEventAll[i];
845227Ssaidi@eecs.umich.edu
855227Ssaidi@eecs.umich.edu    if (vnc)
865396Ssaidi@eecs.umich.edu        vnc->setFrameBuffer(&fb);
875396Ssaidi@eecs.umich.edu}
885396Ssaidi@eecs.umich.edu
895396Ssaidi@eecs.umich.eduHDLcd::~HDLcd()
905396Ssaidi@eecs.umich.edu{
915396Ssaidi@eecs.umich.edu}
925396Ssaidi@eecs.umich.edu
935396Ssaidi@eecs.umich.edu// read registers and frame buffer
945396Ssaidi@eecs.umich.eduTick
955396Ssaidi@eecs.umich.eduHDLcd::read(PacketPtr pkt)
965396Ssaidi@eecs.umich.edu{
975396Ssaidi@eecs.umich.edu    uint32_t data = 0;
985396Ssaidi@eecs.umich.edu    const Addr daddr = pkt->getAddr() - pioAddr;
995396Ssaidi@eecs.umich.edu
1005396Ssaidi@eecs.umich.edu    DPRINTF(HDLcd, "read register BASE+0x%04x size=%d\n", daddr,
1015396Ssaidi@eecs.umich.edu            pkt->getSize());
1025396Ssaidi@eecs.umich.edu
1035396Ssaidi@eecs.umich.edu    assert(pkt->getAddr() >= pioAddr &&
1045396Ssaidi@eecs.umich.edu            pkt->getAddr() < pioAddr + pioSize &&
1055396Ssaidi@eecs.umich.edu            pkt->getSize() == 4);
1065396Ssaidi@eecs.umich.edu
1075396Ssaidi@eecs.umich.edu    switch (daddr) {
1085396Ssaidi@eecs.umich.edu      case Version:
1095396Ssaidi@eecs.umich.edu        data = version;
1105396Ssaidi@eecs.umich.edu        break;
1115396Ssaidi@eecs.umich.edu      case Int_RawStat:
1125396Ssaidi@eecs.umich.edu        data = int_rawstat;
1135396Ssaidi@eecs.umich.edu        break;
1145396Ssaidi@eecs.umich.edu      case Int_Clear:
1155396Ssaidi@eecs.umich.edu        panic("HDLCD INT_CLEAR register is Write-Only\n");
1165396Ssaidi@eecs.umich.edu        break;
1175396Ssaidi@eecs.umich.edu      case Int_Mask:
1185396Ssaidi@eecs.umich.edu        data = int_mask;
1195396Ssaidi@eecs.umich.edu        break;
1205396Ssaidi@eecs.umich.edu      case Int_Status:
1215396Ssaidi@eecs.umich.edu        data = int_status;
1225396Ssaidi@eecs.umich.edu        break;
1235396Ssaidi@eecs.umich.edu      case Fb_Base:
1245396Ssaidi@eecs.umich.edu        data = fb_base;
1255396Ssaidi@eecs.umich.edu        break;
1265396Ssaidi@eecs.umich.edu      case Fb_Line_Length:
1275396Ssaidi@eecs.umich.edu        data = fb_line_length;
1285396Ssaidi@eecs.umich.edu        break;
1295396Ssaidi@eecs.umich.edu      case Fb_Line_Count:
1305396Ssaidi@eecs.umich.edu        data = fb_line_count;
1315396Ssaidi@eecs.umich.edu        break;
1325396Ssaidi@eecs.umich.edu      case Fb_Line_Pitch:
1335396Ssaidi@eecs.umich.edu        data = fb_line_pitch;
1345396Ssaidi@eecs.umich.edu        break;
1355396Ssaidi@eecs.umich.edu      case Bus_Options:
1365396Ssaidi@eecs.umich.edu        data = bus_options;
1375396Ssaidi@eecs.umich.edu        break;
1385396Ssaidi@eecs.umich.edu      case V_Sync:
1395396Ssaidi@eecs.umich.edu        data = v_sync;
1405396Ssaidi@eecs.umich.edu        break;
1415396Ssaidi@eecs.umich.edu      case V_Back_Porch:
1425396Ssaidi@eecs.umich.edu        data = v_back_porch;
1435396Ssaidi@eecs.umich.edu        break;
1445396Ssaidi@eecs.umich.edu      case V_Data:
1455396Ssaidi@eecs.umich.edu        data = v_data;
1465396Ssaidi@eecs.umich.edu        break;
1475396Ssaidi@eecs.umich.edu      case V_Front_Porch:
1485396Ssaidi@eecs.umich.edu        data = v_front_porch;
1495396Ssaidi@eecs.umich.edu        break;
1504781Snate@binkert.org      case H_Sync:
1511852SN/A        data = h_sync;
152955SN/A        break;
153955SN/A      case H_Back_Porch:
154955SN/A        data = h_back_porch;
1553717Sstever@eecs.umich.edu        break;
1563716Sstever@eecs.umich.edu      case H_Data:
157955SN/A        data = h_data;
1581533SN/A        break;
1593716Sstever@eecs.umich.edu      case H_Front_Porch:
1601533SN/A        data = h_front_porch;
1614678Snate@binkert.org        break;
1624678Snate@binkert.org      case Polarities:
1634678Snate@binkert.org        data = polarities;
1644678Snate@binkert.org        break;
1654678Snate@binkert.org      case Command:
1664678Snate@binkert.org        data = command;
1674678Snate@binkert.org        break;
1684678Snate@binkert.org      case Pixel_Format:
1694678Snate@binkert.org        data = pixel_format;
1704678Snate@binkert.org        break;
1714678Snate@binkert.org      case Red_Select:
1724678Snate@binkert.org        data = red_select;
1734678Snate@binkert.org        break;
1744678Snate@binkert.org      case Green_Select:
1754678Snate@binkert.org        data = green_select;
1764678Snate@binkert.org        break;
1774678Snate@binkert.org      case Blue_Select:
1784678Snate@binkert.org        data = blue_select;
1794678Snate@binkert.org        break;
1804678Snate@binkert.org      default:
1814678Snate@binkert.org        panic("Tried to read HDLCD register that doesn't  exist\n", daddr);
1824973Ssaidi@eecs.umich.edu        break;
1834678Snate@binkert.org    }
1844678Snate@binkert.org
1854678Snate@binkert.org    pkt->set<uint32_t>(data);
1864678Snate@binkert.org    pkt->makeAtomicResponse();
1874678Snate@binkert.org    return pioDelay;
1884678Snate@binkert.org}
189955SN/A
190955SN/A// write registers and frame buffer
1912632Sstever@eecs.umich.eduTick
1922632Sstever@eecs.umich.eduHDLcd::write(PacketPtr pkt)
193955SN/A{
194955SN/A    assert(pkt->getAddr() >= pioAddr &&
195955SN/A           pkt->getAddr() < pioAddr + pioSize &&
196955SN/A           pkt->getSize() == 4);
1972632Sstever@eecs.umich.edu
198955SN/A    const uint32_t data = pkt->get<uint32_t>();
1992632Sstever@eecs.umich.edu    const Addr daddr = pkt->getAddr() - pioAddr;
2002632Sstever@eecs.umich.edu
2012632Sstever@eecs.umich.edu    DPRINTF(HDLcd, "write register BASE+%0x04x <= 0x%08x\n", daddr,
2022632Sstever@eecs.umich.edu            pkt->get<uint32_t>());
2032632Sstever@eecs.umich.edu
2042632Sstever@eecs.umich.edu    switch (daddr) {
2052632Sstever@eecs.umich.edu      case Version:
2062632Sstever@eecs.umich.edu        panic("HDLCD VERSION register is read-Only\n");
2072632Sstever@eecs.umich.edu        break;
2082632Sstever@eecs.umich.edu      case Int_RawStat:
2092632Sstever@eecs.umich.edu        int_rawstat = data;
2102632Sstever@eecs.umich.edu        break;
2112632Sstever@eecs.umich.edu      case Int_Clear:
2123718Sstever@eecs.umich.edu        int_clear = data;
2133718Sstever@eecs.umich.edu        break;
2143718Sstever@eecs.umich.edu      case Int_Mask:
2153718Sstever@eecs.umich.edu        int_mask = data;
2163718Sstever@eecs.umich.edu        break;
2173718Sstever@eecs.umich.edu      case Int_Status:
2183718Sstever@eecs.umich.edu        panic("HDLCD INT_STATUS register is read-Only\n");
2193718Sstever@eecs.umich.edu        break;
2203718Sstever@eecs.umich.edu      case Fb_Base:
2213718Sstever@eecs.umich.edu        fb_base = data;
2223718Sstever@eecs.umich.edu        DPRINTF(HDLcd, "HDLCD Frame Buffer located at addr 0x%08x\n", fb_base);
2233718Sstever@eecs.umich.edu        break;
2243718Sstever@eecs.umich.edu      case Fb_Line_Length:
2252634Sstever@eecs.umich.edu        fb_line_length = data;
2262634Sstever@eecs.umich.edu        DPRINTF(HDLcd, "HDLCD res = %d x %d\n", width(), height());
2272632Sstever@eecs.umich.edu        break;
2282638Sstever@eecs.umich.edu      case Fb_Line_Count:
2292632Sstever@eecs.umich.edu        fb_line_count = data;
2302632Sstever@eecs.umich.edu        DPRINTF(HDLcd, "HDLCD res = %d x %d\n", width(), height());
2312632Sstever@eecs.umich.edu        break;
2322632Sstever@eecs.umich.edu      case Fb_Line_Pitch:
2332632Sstever@eecs.umich.edu        fb_line_pitch = data;
2342632Sstever@eecs.umich.edu        break;
2351858SN/A      case Bus_Options: {
2363716Sstever@eecs.umich.edu        BusOptsReg old_bus_options;
2372638Sstever@eecs.umich.edu        old_bus_options = bus_options;
2382638Sstever@eecs.umich.edu        bus_options = data;
2392638Sstever@eecs.umich.edu        if (bus_options.max_outstanding != old_bus_options.max_outstanding)
2402638Sstever@eecs.umich.edu            DPRINTF(HDLcd,
2412638Sstever@eecs.umich.edu                "Changing HDLcd outstanding dma transactions from %d to %d\n",
2422638Sstever@eecs.umich.edu                old_bus_options.max_outstanding, bus_options.max_outstanding);
2432638Sstever@eecs.umich.edu        if (bus_options.burst_len != old_bus_options.burst_len)
2443716Sstever@eecs.umich.edu            DPRINTF(HDLcd,
2452634Sstever@eecs.umich.edu                "Changing HDLcd dma burst length from %d bytes to %d bytes\n",
2462634Sstever@eecs.umich.edu                old_bus_options.burst_len, bus_options.burst_len); }
247955SN/A        break;
2485341Sstever@gmail.com      case V_Sync:
2495341Sstever@gmail.com        v_sync = data;
2505341Sstever@gmail.com        break;
2515341Sstever@gmail.com      case V_Back_Porch:
252955SN/A        v_back_porch = data;
253955SN/A        break;
254955SN/A      case V_Data:
255955SN/A        v_data = data;
256955SN/A        break;
257955SN/A      case V_Front_Porch:
258955SN/A        v_front_porch = data;
2591858SN/A        break;
2601858SN/A      case H_Sync:
2612632Sstever@eecs.umich.edu        h_sync = data;
262955SN/A        break;
2634494Ssaidi@eecs.umich.edu      case H_Back_Porch:
2644494Ssaidi@eecs.umich.edu        h_back_porch = data;
2653716Sstever@eecs.umich.edu        break;
2661105SN/A      case H_Data:
2672667Sstever@eecs.umich.edu        h_data = data;
2682667Sstever@eecs.umich.edu        break;
2692667Sstever@eecs.umich.edu      case H_Front_Porch:
2702667Sstever@eecs.umich.edu        h_front_porch = data;
2712667Sstever@eecs.umich.edu        break;
2722667Sstever@eecs.umich.edu      case Polarities:
2731869SN/A        polarities = data;
2741869SN/A        break;
2751869SN/A      case Command: {
2761869SN/A        CommandReg new_command;
2771869SN/A        new_command = data;
2781065SN/A        if (new_command.enable != command.enable) {
2795341Sstever@gmail.com            DPRINTF(HDLcd, "HDLCD switched %s\n",
2805341Sstever@gmail.com                    new_command.enable==0 ? "off" : "on");
2815341Sstever@gmail.com            if (new_command.enable) {
2825341Sstever@gmail.com                doUpdateParams = true;
2835341Sstever@gmail.com                if (!frameUnderway) {
2845341Sstever@gmail.com                    schedule(startFrameEvent, clockEdge());
2855341Sstever@gmail.com                }
2865341Sstever@gmail.com            }
2875341Sstever@gmail.com        }
2885341Sstever@gmail.com        command = new_command; }
2895341Sstever@gmail.com        break;
2905341Sstever@gmail.com      case Pixel_Format:
2915341Sstever@gmail.com        pixel_format = data;
2925341Sstever@gmail.com        DPRINTF(HDLcd, "HDLCD res = %d x %d\n", width(), height());
2935341Sstever@gmail.com        DPRINTF(HDLcd, "HDLCD bytes per pixel = %d\n", bytesPerPixel());
2945341Sstever@gmail.com        DPRINTF(HDLcd, "HDLCD endianness = %s\n",
2955341Sstever@gmail.com                pixel_format.big_endian ? "big" : "little");
2965341Sstever@gmail.com        break;
2975341Sstever@gmail.com      case Red_Select:
2985341Sstever@gmail.com        red_select = data;
2995341Sstever@gmail.com        break;
3005341Sstever@gmail.com      case Green_Select:
3015341Sstever@gmail.com        green_select = data;
3025341Sstever@gmail.com        break;
3035341Sstever@gmail.com      case Blue_Select:
3045341Sstever@gmail.com        blue_select = data;
3055341Sstever@gmail.com        break;
3065341Sstever@gmail.com      default:
3075341Sstever@gmail.com        panic("Tried to write HDLCD register that doesn't exist\n", daddr);
3085341Sstever@gmail.com        break;
3095341Sstever@gmail.com    }
3105341Sstever@gmail.com
3115341Sstever@gmail.com    pkt->makeAtomicResponse();
3125341Sstever@gmail.com    return pioDelay;
3135341Sstever@gmail.com}
3145341Sstever@gmail.com
3155341Sstever@gmail.comvoid
3165341Sstever@gmail.comHDLcd::updateVideoParams(bool unserializing = false)
3175341Sstever@gmail.com{
3185341Sstever@gmail.com    const uint16_t bpp M5_VAR_USED = bytesPerPixel() << 3;
3195341Sstever@gmail.com
3205341Sstever@gmail.com    // Workaround configuration bugs where multiple display
3215341Sstever@gmail.com    // controllers are attached to the same VNC server by reattaching
3225341Sstever@gmail.com    // enabled devices. This isn't ideal, but works as long as only
3235341Sstever@gmail.com    // one display controller is active at a time.
3245341Sstever@gmail.com    if (command.enable && vnc)
3255341Sstever@gmail.com        vnc->setFrameBuffer(&fb);
3265341Sstever@gmail.com
3275341Sstever@gmail.com    // updating these parameters while LCD is enabled is not supported
3285344Sstever@gmail.com    if (frameUnderway && !unserializing)
3295341Sstever@gmail.com        panic("Attempting to change some HDLCD parameters while the controller"
3305341Sstever@gmail.com                " is active is not allowed");
3315341Sstever@gmail.com
3325341Sstever@gmail.com    // resize the virtualDisplayBuffer unless we are unserializing - it may
3335341Sstever@gmail.com    //   have changed size
3342632Sstever@eecs.umich.edu    // there must be no outstanding DMA transactions for this to work
3355199Sstever@gmail.com    if (!unserializing) {
3363918Ssaidi@eecs.umich.edu        assert(dmaPendingNum == 0);
3373918Ssaidi@eecs.umich.edu
3383940Ssaidi@eecs.umich.edu        virtualDisplayBuffer.resize(bytesPerPixel() * area());
3394781Snate@binkert.org        fb.resize(width(), height());
3404781Snate@binkert.org        fb.clear();
3413918Ssaidi@eecs.umich.edu
3424781Snate@binkert.org        std::fill(virtualDisplayBuffer.begin(), virtualDisplayBuffer.end(),
3434781Snate@binkert.org                  0);
3443918Ssaidi@eecs.umich.edu    }
3454781Snate@binkert.org
3464781Snate@binkert.org    DPRINTF(HDLcd, "bpp = %d\n", bpp);
3473940Ssaidi@eecs.umich.edu    DPRINTF(HDLcd, "display size = %d x %d\n", width(), height());
3483942Ssaidi@eecs.umich.edu#if TRACING_ON
3493940Ssaidi@eecs.umich.edu    const size_t totalLinesPerFrame = v_back_porch.val + 1 +
3503918Ssaidi@eecs.umich.edu                                      v_data.val + 1 +
3513918Ssaidi@eecs.umich.edu                                      v_front_porch.val + 1 +
352955SN/A                                      v_sync.val + 1;
3531858SN/A    const double fps = (double)SimClock::Frequency /
3543918Ssaidi@eecs.umich.edu            (double)(PClksPerLine() * totalLinesPerFrame * pixelClock);
3553918Ssaidi@eecs.umich.edu#endif
3563918Ssaidi@eecs.umich.edu    DPRINTF(HDLcd, "simulated refresh rate ~ %.1ffps generating ~ %.1fMB/s "
3573918Ssaidi@eecs.umich.edu            "traffic ([%.1fMHz, T=%d sim clocks] pclk, %d bpp => %.1fMB/s peak requirement)\n",
3583940Ssaidi@eecs.umich.edu            fps,
3593940Ssaidi@eecs.umich.edu            fps * virtualDisplayBuffer.size() / 1024 / 1024,
3603918Ssaidi@eecs.umich.edu            (double)SimClock::Frequency / pixelClock / 1000000.0,
3613918Ssaidi@eecs.umich.edu            pixelClock,
3623918Ssaidi@eecs.umich.edu            bpp,
3633918Ssaidi@eecs.umich.edu            (double)(SimClock::Frequency / pixelClock * (bpp / 8)) / 1024 / 1024);
3643918Ssaidi@eecs.umich.edu}
3653918Ssaidi@eecs.umich.edu
3663918Ssaidi@eecs.umich.eduvoid
3673918Ssaidi@eecs.umich.eduHDLcd::startFrame()
3683918Ssaidi@eecs.umich.edu{
3693940Ssaidi@eecs.umich.edu    // 0. Check that we are in the appropriate state
3703918Ssaidi@eecs.umich.edu    assert(!frameUnderway);
3713918Ssaidi@eecs.umich.edu    if (!command.enable)
3721851SN/A        return;
3731851SN/A    DPRINTF(HDLcd, "Frame read started\n");
3741858SN/A    if (doUpdateParams) {
3755200Sstever@gmail.com        updateVideoParams();
376955SN/A        doUpdateParams = false;
3773053Sstever@eecs.umich.edu    }
3783053Sstever@eecs.umich.edu    frameUnderway = true;
3793053Sstever@eecs.umich.edu    assert(!virtualDisplayBuffer.empty());
3803053Sstever@eecs.umich.edu    assert(pixelBufferSize == 0);
3813053Sstever@eecs.umich.edu    assert(dmaBytesInFlight == 0);
3823053Sstever@eecs.umich.edu    assert(dmaPendingNum == 0);
3833053Sstever@eecs.umich.edu    assert(dmaDoneEventFree.size() == dmaDoneEventAll.size());
3843053Sstever@eecs.umich.edu    assert(!renderPixelEvent.scheduled());
3853053Sstever@eecs.umich.edu    // currently only support positive line pitches equal to the line length
3864742Sstever@eecs.umich.edu    assert(width() * bytesPerPixel() == fb_line_pitch);
3874742Sstever@eecs.umich.edu
3883053Sstever@eecs.umich.edu    // 1. Start DMA'ing the frame; subsequent transactions created as we go
3893053Sstever@eecs.umich.edu    dmaCurAddr = dmaStartAddr = fb_base;
3903053Sstever@eecs.umich.edu    dmaMaxAddr = static_cast<Addr>(width() * height() * bytesPerPixel()) +
3913053Sstever@eecs.umich.edu                    dmaCurAddr;
3923053Sstever@eecs.umich.edu    frameReadStartTime = curTick();
3933053Sstever@eecs.umich.edu    pixelIndex = 0;
3943053Sstever@eecs.umich.edu    frameUnderrun = false;
3953053Sstever@eecs.umich.edu    fillPixelBuffer();
3963053Sstever@eecs.umich.edu
3972667Sstever@eecs.umich.edu    // 2. Schedule first pixelclock read; subsequent reads generated as we go
3984554Sbinkertn@umich.edu    Tick firstPixelReadTick = curTick() + pixelClock * (
3994554Sbinkertn@umich.edu                                  PClksPerLine() * (v_sync.val + 1 +
4002667Sstever@eecs.umich.edu                                                    v_back_porch.val + 1) +
4014554Sbinkertn@umich.edu                                  h_sync.val + 1 +
4024554Sbinkertn@umich.edu                                  h_back_porch.val + 1);
4034554Sbinkertn@umich.edu    schedule(renderPixelEvent, firstPixelReadTick);
4044554Sbinkertn@umich.edu}
4054554Sbinkertn@umich.edu
4064554Sbinkertn@umich.eduvoid
4074554Sbinkertn@umich.eduHDLcd::fillPixelBuffer()
4084781Snate@binkert.org{
4094554Sbinkertn@umich.edu    // - am I under the LCD dma transaction total?
4104554Sbinkertn@umich.edu    // - do I have more data to transfer?
4112667Sstever@eecs.umich.edu    // - have I not yet underrun for this frame?
4124554Sbinkertn@umich.edu    // - is there room to put the data in the pixel buffer including any
4134554Sbinkertn@umich.edu    //   outstanding dma transfers in flight?
4144554Sbinkertn@umich.edu    while ((dmaPendingNum < maxOutstandingDma()) &&
4154554Sbinkertn@umich.edu           (dmaMaxAddr > dmaCurAddr) &&
4162667Sstever@eecs.umich.edu           !frameUnderrun &&
4174554Sbinkertn@umich.edu           bytesFreeInPixelBuffer() > dmaBurstLength() * AXI_PORT_WIDTH) {
4182667Sstever@eecs.umich.edu        // try largest transaction size allowed first but switch to smaller
4194554Sbinkertn@umich.edu        // sizes for trailing bytes
4204554Sbinkertn@umich.edu        size_t transaction_size = dmaBurstLength() * AXI_PORT_WIDTH;
4212667Sstever@eecs.umich.edu        while (transaction_size > (dmaMaxAddr - dmaCurAddr))
4222638Sstever@eecs.umich.edu            transaction_size >>= 1;
4232638Sstever@eecs.umich.edu        assert(transaction_size > 0);
4242638Sstever@eecs.umich.edu
4253716Sstever@eecs.umich.edu        // concurrent dma reads need different dma done events
4263716Sstever@eecs.umich.edu        // due to assertion in scheduling state
4271858SN/A        ++dmaPendingNum;
4285227Ssaidi@eecs.umich.edu
4295227Ssaidi@eecs.umich.edu        assert(!dmaDoneEventFree.empty());
4305227Ssaidi@eecs.umich.edu        DmaDoneEvent *event(dmaDoneEventFree.back());
4315227Ssaidi@eecs.umich.edu        dmaDoneEventFree.pop_back();
4325227Ssaidi@eecs.umich.edu        assert(event);
4335227Ssaidi@eecs.umich.edu        assert(!event->scheduled());
4345227Ssaidi@eecs.umich.edu
4355227Ssaidi@eecs.umich.edu        // We use a uncachable request here because the requests from the CPU
4365227Ssaidi@eecs.umich.edu        // will be uncacheable as well. If we have uncacheable and cacheable
4375227Ssaidi@eecs.umich.edu        // requests in the memory system for the same address it won't be
4385227Ssaidi@eecs.umich.edu        // pleased
4395227Ssaidi@eecs.umich.edu        uint8_t *const dma_dst(
4405274Ssaidi@eecs.umich.edu            virtualDisplayBuffer.data() + dmaCurAddr - dmaStartAddr);
4415227Ssaidi@eecs.umich.edu        event->setTransactionSize(transaction_size);
4425227Ssaidi@eecs.umich.edu        dmaPort.dmaAction(MemCmd::ReadReq, dmaCurAddr, transaction_size, event,
4435227Ssaidi@eecs.umich.edu                          dma_dst, 0, Request::UNCACHEABLE);
4445204Sstever@gmail.com        dmaCurAddr += transaction_size;
4455204Sstever@gmail.com        dmaBytesInFlight += transaction_size;
4465204Sstever@gmail.com    }
4475204Sstever@gmail.com}
4485204Sstever@gmail.com
4495204Sstever@gmail.comvoid
4505204Sstever@gmail.comHDLcd::renderPixel()
4515204Sstever@gmail.com{
4525204Sstever@gmail.com    // try to handle multiple pixels at a time; doing so reduces the accuracy
4535204Sstever@gmail.com    //   of the underrun detection but lowers simulation overhead
4545204Sstever@gmail.com    const size_t count = 32;
4555204Sstever@gmail.com    assert(width() % count == 0); // not set up to handle trailing pixels
4565204Sstever@gmail.com
4575204Sstever@gmail.com    // have we underrun on this frame anytime before?
4585204Sstever@gmail.com    if (frameUnderrun) {
4595204Sstever@gmail.com        // the LCD controller gives up on a frame if an underrun occurs and
4605204Sstever@gmail.com        //   resumes regular operation on the next frame
4615204Sstever@gmail.com        pixelBufferSize = 0;
4625204Sstever@gmail.com    } else {
4633118Sstever@eecs.umich.edu        // did we underrun on this set of pixels?
4643118Sstever@eecs.umich.edu        if (pixelBufferSize < bytesPerPixel() * count) {
4653118Sstever@eecs.umich.edu            warn("HDLcd controller buffer underrun\n");
4663118Sstever@eecs.umich.edu            frameUnderrun = true;
4673118Sstever@eecs.umich.edu            int_rawstat.underrun = 1;
4683118Sstever@eecs.umich.edu            if (!intEvent.scheduled())
4693118Sstever@eecs.umich.edu                schedule(intEvent, clockEdge());
4703118Sstever@eecs.umich.edu        } else {
4713118Sstever@eecs.umich.edu            // emulate the pixel read from the internal buffer
4723118Sstever@eecs.umich.edu            pixelBufferSize -= bytesPerPixel() * count;
4733118Sstever@eecs.umich.edu        }
4743716Sstever@eecs.umich.edu    }
4753118Sstever@eecs.umich.edu
4763118Sstever@eecs.umich.edu    // the DMA may have previously stalled due to the buffer being full;
4773118Sstever@eecs.umich.edu    //   give it a kick; it knows not to fill if at end of frame, underrun, etc
4783118Sstever@eecs.umich.edu    if (!fillPixelBufferEvent.scheduled())
4793118Sstever@eecs.umich.edu        schedule(fillPixelBufferEvent, clockEdge());
4803118Sstever@eecs.umich.edu
4813118Sstever@eecs.umich.edu    // schedule the next pixel read according to where it is in the frame
4823118Sstever@eecs.umich.edu    pixelIndex += count;
4833118Sstever@eecs.umich.edu    assert(pixelIndex <= width() * height());
4843716Sstever@eecs.umich.edu    size_t x = pixelIndex % width();
4853118Sstever@eecs.umich.edu    Tick nextEventTick = curTick();
4863118Sstever@eecs.umich.edu    if (x == 0) {
4873118Sstever@eecs.umich.edu        // start of new line
4883118Sstever@eecs.umich.edu        nextEventTick += pixelClock * ((h_front_porch.val + 1) +
4893118Sstever@eecs.umich.edu                                       (h_back_porch.val + 1) +
4903118Sstever@eecs.umich.edu                                       (h_sync.val + 1));
4913118Sstever@eecs.umich.edu        if (pixelIndex == width() * height()) {
4923118Sstever@eecs.umich.edu            // end of frame
4933118Sstever@eecs.umich.edu            nextEventTick += PClksPerLine() * (v_front_porch.val + 1) *
4943118Sstever@eecs.umich.edu                             pixelClock;
4953483Ssaidi@eecs.umich.edu            schedule(endFrameEvent, nextEventTick);
4963494Ssaidi@eecs.umich.edu            return;
4973494Ssaidi@eecs.umich.edu        }
4983483Ssaidi@eecs.umich.edu    } else {
4993483Ssaidi@eecs.umich.edu        nextEventTick += pixelClock * count;
5003483Ssaidi@eecs.umich.edu    }
5013053Sstever@eecs.umich.edu
5023053Sstever@eecs.umich.edu    schedule(renderPixelEvent, nextEventTick);
5033918Ssaidi@eecs.umich.edu}
5043053Sstever@eecs.umich.edu
5053053Sstever@eecs.umich.eduPixelConverter
5063053Sstever@eecs.umich.eduHDLcd::pixelConverter() const
5073053Sstever@eecs.umich.edu{
5083053Sstever@eecs.umich.edu    ByteOrder byte_order(
5091858SN/A        pixel_format.big_endian ? BigEndianByteOrder : LittleEndianByteOrder);
5101858SN/A
5111858SN/A    /* Some Linux kernels have a broken driver that swaps the red and
5121858SN/A     * blue color select registers. */
5131858SN/A    if (!workaround_swap_rb) {
5141858SN/A        return PixelConverter(
5151859SN/A            bytesPerPixel(),
5161858SN/A            red_select.offset, green_select.offset, blue_select.offset,
5171858SN/A            red_select.size, green_select.size, blue_select.size,
5181858SN/A            byte_order);
5191859SN/A    } else {
5201859SN/A        return PixelConverter(
5211862SN/A            bytesPerPixel(),
5223053Sstever@eecs.umich.edu            blue_select.offset, green_select.offset, red_select.offset,
5233053Sstever@eecs.umich.edu            blue_select.size, green_select.size, red_select.size,
5243053Sstever@eecs.umich.edu            byte_order);
5253053Sstever@eecs.umich.edu    }
5261859SN/A}
5271859SN/A
5281859SN/Avoid
5291859SN/AHDLcd::endFrame() {
5301859SN/A    assert(pixelBufferSize == 0);
5311859SN/A    assert(dmaPendingNum == 0);
5321859SN/A    assert(dmaBytesInFlight == 0);
5331859SN/A    assert(dmaDoneEventFree.size() == dmaDoneEventAll.size());
5341862SN/A
5351859SN/A    fb.copyIn(virtualDisplayBuffer, pixelConverter());
5361859SN/A
5371859SN/A    if (vnc)
5381858SN/A        vnc->setDirty();
5391858SN/A
5402139SN/A    if (enableCapture) {
5414202Sbinkertn@umich.edu        if (!pic)
5424202Sbinkertn@umich.edu            pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true);
5432139SN/A
5442155SN/A        assert(pic);
5454202Sbinkertn@umich.edu        pic->seekp(0);
5464202Sbinkertn@umich.edu        bmp.write(*pic);
5474202Sbinkertn@umich.edu    }
5482155SN/A
5491869SN/A    // start the next frame
5501869SN/A    frameUnderway = false;
5511869SN/A    startFrame();
5521869SN/A}
5534202Sbinkertn@umich.edu
5544202Sbinkertn@umich.eduvoid
5554202Sbinkertn@umich.eduHDLcd::dmaDone(DmaDoneEvent *event)
5564202Sbinkertn@umich.edu{
5574202Sbinkertn@umich.edu    const size_t transactionLength = event->getTransactionSize();
5584202Sbinkertn@umich.edu    assert(pixelBufferSize + transactionLength < PIXEL_BUFFER_CAPACITY);
5594202Sbinkertn@umich.edu    assert(dmaCurAddr <= dmaMaxAddr);
5604202Sbinkertn@umich.edu
5615341Sstever@gmail.com    dmaDoneEventFree.push_back(event);
5625341Sstever@gmail.com    --dmaPendingNum;
5635341Sstever@gmail.com    assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY - dmaDoneEventFree.size() ==
5645342Sstever@gmail.com            dmaPendingNum);
5655342Sstever@gmail.com
5664202Sbinkertn@umich.edu    // add the data to the pixel buffer
5674202Sbinkertn@umich.edu    dmaBytesInFlight -= transactionLength;
5684202Sbinkertn@umich.edu    pixelBufferSize += transactionLength;
5694202Sbinkertn@umich.edu
5704202Sbinkertn@umich.edu    // schedule another dma transaction if:
5711869SN/A    // - we're not done reading the frame
5724202Sbinkertn@umich.edu    // - there is sufficient room in the pixel buffer for another transaction
5731869SN/A    // - another fillPixelBufferEvent is not already scheduled
5742508SN/A    const size_t targetTransSize = dmaBurstLength() * AXI_PORT_WIDTH;
5752508SN/A    if ((dmaCurAddr < dmaMaxAddr) &&
5762508SN/A        (bytesFreeInPixelBuffer() + targetTransSize < PIXEL_BUFFER_CAPACITY) &&
5772508SN/A        !fillPixelBufferEvent.scheduled()) {
5784202Sbinkertn@umich.edu        schedule(fillPixelBufferEvent, clockEdge());
5791869SN/A    }
5805385Sstever@gmail.com}
5815385Sstever@gmail.com
5825385Sstever@gmail.comvoid
5835385Sstever@gmail.comHDLcd::serialize(std::ostream &os)
5841869SN/A{
5851869SN/A    DPRINTF(HDLcd, "Serializing ARM HDLCD\n");
5861869SN/A
5871869SN/A    const uint32_t version_serial = version;
5881869SN/A    SERIALIZE_SCALAR(version_serial);
5891965SN/A    const uint32_t int_rawstat_serial = int_rawstat;
5901965SN/A    SERIALIZE_SCALAR(int_rawstat_serial);
5911965SN/A    const uint32_t int_clear_serial = int_clear;
5921869SN/A    SERIALIZE_SCALAR(int_clear_serial);
5931869SN/A    const uint32_t int_mask_serial = int_mask;
5942733Sktlim@umich.edu    SERIALIZE_SCALAR(int_mask_serial);
5951884SN/A    const uint32_t int_status_serial = int_status;
5963356Sbinkertn@umich.edu    SERIALIZE_SCALAR(int_status_serial);
5973356Sbinkertn@umich.edu
5983356Sbinkertn@umich.edu    SERIALIZE_SCALAR(fb_base);
5994773Snate@binkert.org    SERIALIZE_SCALAR(fb_line_length);
6001869SN/A
6011858SN/A    const uint32_t fb_line_count_serial = fb_line_count;
6021869SN/A    SERIALIZE_SCALAR(fb_line_count_serial);
6031869SN/A
6041869SN/A    SERIALIZE_SCALAR(fb_line_pitch);
6051858SN/A
6062761Sstever@eecs.umich.edu    const uint32_t bus_options_serial = bus_options;
6071869SN/A    SERIALIZE_SCALAR(bus_options_serial);
6085385Sstever@gmail.com    const uint32_t v_sync_serial = v_sync;
6095385Sstever@gmail.com    SERIALIZE_SCALAR(v_sync_serial);
6103584Ssaidi@eecs.umich.edu    const uint32_t v_back_porch_serial = v_back_porch;
6111869SN/A    SERIALIZE_SCALAR(v_back_porch_serial);
6121869SN/A    const uint32_t v_data_serial = v_data;
6131869SN/A    SERIALIZE_SCALAR(v_data_serial);
6141869SN/A    const uint32_t v_front_porch_serial = v_front_porch;
6151869SN/A    SERIALIZE_SCALAR(v_front_porch_serial);
6161869SN/A    const uint32_t h_sync_serial = h_sync;
6171858SN/A    SERIALIZE_SCALAR(h_sync_serial);
618955SN/A    const uint32_t h_back_porch_serial = h_back_porch;
619955SN/A    SERIALIZE_SCALAR(h_back_porch_serial);
6201869SN/A    const uint32_t h_data_serial = h_data;
6211869SN/A    SERIALIZE_SCALAR(h_data_serial);
6221869SN/A    const uint32_t h_front_porch_serial = h_front_porch;
6231869SN/A    SERIALIZE_SCALAR(h_front_porch_serial);
6241869SN/A    const uint32_t polarities_serial = polarities;
6251869SN/A    SERIALIZE_SCALAR(polarities_serial);
6261869SN/A    const uint32_t command_serial = command;
6271869SN/A    SERIALIZE_SCALAR(command_serial);
6281869SN/A    const uint32_t pixel_format_serial = pixel_format;
6291869SN/A    SERIALIZE_SCALAR(pixel_format_serial);
6301869SN/A    const uint32_t red_select_serial = red_select;
6311869SN/A    SERIALIZE_SCALAR(red_select_serial);
6321869SN/A    const uint32_t green_select_serial = green_select;
6331869SN/A    SERIALIZE_SCALAR(green_select_serial);
6341869SN/A    const uint32_t blue_select_serial = blue_select;
6351869SN/A    SERIALIZE_SCALAR(blue_select_serial);
6361869SN/A
6371869SN/A    SERIALIZE_SCALAR(frameReadStartTime);
6381869SN/A    SERIALIZE_SCALAR(dmaStartAddr);
6391869SN/A    SERIALIZE_SCALAR(dmaCurAddr);
6401869SN/A    SERIALIZE_SCALAR(dmaMaxAddr);
6411869SN/A    SERIALIZE_SCALAR(dmaPendingNum);
6421869SN/A    SERIALIZE_SCALAR(frameUnderrun);
6431869SN/A
6441869SN/A    arrayParamOut(os, "virtualDisplayBuffer", virtualDisplayBuffer);
6451869SN/A
6461869SN/A    SERIALIZE_SCALAR(pixelBufferSize);
6471869SN/A    SERIALIZE_SCALAR(pixelIndex);
6481869SN/A    SERIALIZE_SCALAR(doUpdateParams);
6493716Sstever@eecs.umich.edu    SERIALIZE_SCALAR(frameUnderway);
6503356Sbinkertn@umich.edu    SERIALIZE_SCALAR(dmaBytesInFlight);
6513356Sbinkertn@umich.edu
6523356Sbinkertn@umich.edu    Tick start_event_time = 0;
6533356Sbinkertn@umich.edu    Tick end_event_time = 0;
6543356Sbinkertn@umich.edu    Tick render_pixel_event_time = 0;
6553356Sbinkertn@umich.edu    Tick fill_pixel_buffer_event_time = 0;
6564781Snate@binkert.org    Tick int_event_time = 0;
6571869SN/A    if (startFrameEvent.scheduled())
6581869SN/A        start_event_time = startFrameEvent.when();
6591869SN/A    if (endFrameEvent.scheduled())
6601869SN/A        end_event_time = endFrameEvent.when();
6611869SN/A    if (renderPixelEvent.scheduled())
6621869SN/A        render_pixel_event_time = renderPixelEvent.when();
6631869SN/A    if (fillPixelBufferEvent.scheduled())
6642655Sstever@eecs.umich.edu        fill_pixel_buffer_event_time = fillPixelBufferEvent.when();
6652655Sstever@eecs.umich.edu    if (intEvent.scheduled())
6662655Sstever@eecs.umich.edu        int_event_time = intEvent.when();
6672655Sstever@eecs.umich.edu    SERIALIZE_SCALAR(start_event_time);
6682655Sstever@eecs.umich.edu    SERIALIZE_SCALAR(end_event_time);
6692655Sstever@eecs.umich.edu    SERIALIZE_SCALAR(render_pixel_event_time);
6702655Sstever@eecs.umich.edu    SERIALIZE_SCALAR(fill_pixel_buffer_event_time);
6712655Sstever@eecs.umich.edu    SERIALIZE_SCALAR(int_event_time);
6722655Sstever@eecs.umich.edu
6732655Sstever@eecs.umich.edu    vector<Tick> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY);
6742655Sstever@eecs.umich.edu    vector<size_t> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY);
6752655Sstever@eecs.umich.edu    for (int x = 0; x < MAX_OUTSTANDING_DMA_REQ_CAPACITY; ++x) {
6762655Sstever@eecs.umich.edu        dma_done_event_tick[x] = dmaDoneEventAll[x].scheduled() ?
6772655Sstever@eecs.umich.edu            dmaDoneEventAll[x].when() : 0;
6782655Sstever@eecs.umich.edu        dma_done_event_burst_len[x] = dmaDoneEventAll[x].scheduled() ?
6792655Sstever@eecs.umich.edu            dmaDoneEventAll[x].getTransactionSize() : 0;
6802655Sstever@eecs.umich.edu    }
6812655Sstever@eecs.umich.edu    arrayParamOut(os, "dma_done_event_tick", dma_done_event_tick);
6822655Sstever@eecs.umich.edu    arrayParamOut(os, "dma_done_event_burst_length", dma_done_event_burst_len);
6832655Sstever@eecs.umich.edu}
6842655Sstever@eecs.umich.edu
6852655Sstever@eecs.umich.eduvoid
6862655Sstever@eecs.umich.eduHDLcd::unserialize(Checkpoint *cp, const std::string &section)
6872655Sstever@eecs.umich.edu{
6882655Sstever@eecs.umich.edu    uint32_t version_serial, int_rawstat_serial, int_clear_serial,
6892655Sstever@eecs.umich.edu            int_mask_serial, int_status_serial, fb_line_count_serial,
6902638Sstever@eecs.umich.edu            bus_options_serial, v_sync_serial, v_back_porch_serial,
6912638Sstever@eecs.umich.edu            v_data_serial, v_front_porch_serial, h_sync_serial,
6923716Sstever@eecs.umich.edu            h_back_porch_serial, h_data_serial, h_front_porch_serial,
6932638Sstever@eecs.umich.edu            polarities_serial, command_serial, pixel_format_serial,
6942638Sstever@eecs.umich.edu            red_select_serial, green_select_serial, blue_select_serial;
6951869SN/A
6961869SN/A    DPRINTF(HDLcd, "Unserializing ARM HDLCD\n");
6973546Sgblack@eecs.umich.edu
6983546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(version_serial);
6993546Sgblack@eecs.umich.edu    version = version_serial;
7003546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(int_rawstat_serial);
7014202Sbinkertn@umich.edu    int_rawstat = int_rawstat_serial;
7023546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(int_clear_serial);
7033546Sgblack@eecs.umich.edu    int_clear = int_clear_serial;
7043546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(int_mask_serial);
7053546Sgblack@eecs.umich.edu    int_mask = int_mask_serial;
7063546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(int_status_serial);
7074781Snate@binkert.org    int_status = int_status_serial;
7084781Snate@binkert.org
7094781Snate@binkert.org    UNSERIALIZE_SCALAR(fb_base);
7104781Snate@binkert.org    UNSERIALIZE_SCALAR(fb_line_length);
7114781Snate@binkert.org
7124781Snate@binkert.org    UNSERIALIZE_SCALAR(fb_line_count_serial);
7134781Snate@binkert.org    fb_line_count = fb_line_count_serial;
7144781Snate@binkert.org
7154781Snate@binkert.org    UNSERIALIZE_SCALAR(fb_line_pitch);
7164781Snate@binkert.org
7174781Snate@binkert.org    UNSERIALIZE_SCALAR(bus_options_serial);
7184781Snate@binkert.org    bus_options = bus_options_serial;
7193546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(v_sync_serial);
7203546Sgblack@eecs.umich.edu    v_sync = v_sync_serial;
7213546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(v_back_porch_serial);
7224781Snate@binkert.org    v_back_porch = v_back_porch_serial;
7233546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(v_data_serial);
7243546Sgblack@eecs.umich.edu    v_data = v_data_serial;
7253546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(v_front_porch_serial);
7263546Sgblack@eecs.umich.edu    v_front_porch = v_front_porch_serial;
7273546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(h_sync_serial);
7283546Sgblack@eecs.umich.edu    h_sync = h_sync_serial;
7293546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(h_back_porch_serial);
7303546Sgblack@eecs.umich.edu    h_back_porch = h_back_porch_serial;
7313546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(h_data_serial);
7323546Sgblack@eecs.umich.edu    h_data = h_data_serial;
7334202Sbinkertn@umich.edu    UNSERIALIZE_SCALAR(h_front_porch_serial);
7343546Sgblack@eecs.umich.edu    h_front_porch = h_front_porch_serial;
7353546Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(polarities_serial);
7363546Sgblack@eecs.umich.edu    polarities = polarities_serial;
737955SN/A    UNSERIALIZE_SCALAR(command_serial);
738955SN/A    command = command_serial;
739955SN/A    UNSERIALIZE_SCALAR(pixel_format_serial);
740955SN/A    pixel_format = pixel_format_serial;
7411858SN/A    UNSERIALIZE_SCALAR(red_select_serial);
7421858SN/A    red_select = red_select_serial;
7431858SN/A    UNSERIALIZE_SCALAR(green_select_serial);
7442632Sstever@eecs.umich.edu    green_select = green_select_serial;
7452632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(blue_select_serial);
7465343Sstever@gmail.com    blue_select = blue_select_serial;
7475343Sstever@gmail.com
7485343Sstever@gmail.com    UNSERIALIZE_SCALAR(frameReadStartTime);
7494773Snate@binkert.org    UNSERIALIZE_SCALAR(dmaStartAddr);
7504773Snate@binkert.org    UNSERIALIZE_SCALAR(dmaCurAddr);
7512632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(dmaMaxAddr);
7522632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(dmaPendingNum);
7532632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(frameUnderrun);
7542023SN/A    UNSERIALIZE_SCALAR(dmaBytesInFlight);
7552632Sstever@eecs.umich.edu
7562632Sstever@eecs.umich.edu    arrayParamIn(cp, section, "virtualDisplayBuffer", virtualDisplayBuffer);
7572632Sstever@eecs.umich.edu
7582632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(pixelBufferSize);
7592632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(pixelIndex);
7603716Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(doUpdateParams);
7615342Sstever@gmail.com    UNSERIALIZE_SCALAR(frameUnderway);
7622632Sstever@eecs.umich.edu
7632632Sstever@eecs.umich.edu    Tick start_event_time = 0;
7642632Sstever@eecs.umich.edu    Tick end_event_time = 0;
7652632Sstever@eecs.umich.edu    Tick render_pixel_event_time = 0;
7662023SN/A    Tick fill_pixel_buffer_event_time = 0;
7672632Sstever@eecs.umich.edu    Tick int_event_time = 0;
7682632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(start_event_time);
7695342Sstever@gmail.com    UNSERIALIZE_SCALAR(end_event_time);
7701889SN/A    UNSERIALIZE_SCALAR(render_pixel_event_time);
7712632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(fill_pixel_buffer_event_time);
7722632Sstever@eecs.umich.edu    UNSERIALIZE_SCALAR(int_event_time);
7732632Sstever@eecs.umich.edu    if (start_event_time)
7742632Sstever@eecs.umich.edu        schedule(startFrameEvent, start_event_time);
7753716Sstever@eecs.umich.edu    if (end_event_time)
7763716Sstever@eecs.umich.edu        schedule(endFrameEvent, end_event_time);
7775342Sstever@gmail.com    if (render_pixel_event_time)
7782632Sstever@eecs.umich.edu        schedule(renderPixelEvent, render_pixel_event_time);
7792632Sstever@eecs.umich.edu    if (fill_pixel_buffer_event_time)
7802632Sstever@eecs.umich.edu        schedule(fillPixelBufferEvent, fill_pixel_buffer_event_time);
7812632Sstever@eecs.umich.edu    if (int_event_time)
7822632Sstever@eecs.umich.edu        schedule(intEvent, int_event_time);
7832632Sstever@eecs.umich.edu
7842632Sstever@eecs.umich.edu    vector<Tick> dma_done_event_tick(MAX_OUTSTANDING_DMA_REQ_CAPACITY);
7851888SN/A    vector<Tick> dma_done_event_burst_len(MAX_OUTSTANDING_DMA_REQ_CAPACITY);
7861888SN/A    arrayParamIn(cp, section, "dma_done_event_tick", dma_done_event_tick);
7871869SN/A    arrayParamIn(cp, section, "dma_done_event_burst_length", dma_done_event_burst_len);
7881869SN/A    dmaDoneEventFree.clear();
7891858SN/A    for (int x = 0; x < MAX_OUTSTANDING_DMA_REQ_CAPACITY; ++x) {
7905341Sstever@gmail.com        if (dma_done_event_tick[x]) {
7912598SN/A            dmaDoneEventAll[x].setTransactionSize(dma_done_event_burst_len[x]);
7922598SN/A            schedule(dmaDoneEventAll[x], dma_done_event_tick[x]);
7932598SN/A        } else
7942598SN/A            dmaDoneEventFree.push_back(&dmaDoneEventAll[x]);
7951858SN/A    }
7961858SN/A    assert(MAX_OUTSTANDING_DMA_REQ_CAPACITY - dmaDoneEventFree.size() == dmaPendingNum);
7971858SN/A
7981858SN/A    if (frameUnderway) {
7991858SN/A        updateVideoParams(true);
8001858SN/A        fb.resize(width(), height());
8011858SN/A        fb.copyIn(virtualDisplayBuffer, pixelConverter());
8021858SN/A        if (vnc)
8031858SN/A            vnc->setDirty();
8041871SN/A    }
8051858SN/A}
8061858SN/A
8071858SN/Avoid
8081858SN/AHDLcd::generateInterrupt()
8091858SN/A{
8101858SN/A    int_status = int_rawstat & int_mask;
8111858SN/A    DPRINTF(HDLcd, "Generate Interrupt: int_rawstat=0x%08x int_mask=0x%08x "
8121858SN/A            "int_status=0x%08x\n",
8131858SN/A            (uint32_t)int_rawstat, (uint32_t)int_mask, (uint32_t)int_status);
8141858SN/A
8151858SN/A    if (int_status != 0) {
8161859SN/A        gic->sendInt(intNum);
8171859SN/A        DPRINTF(HDLcd, " -- Generated\n");
8181869SN/A    }
8191888SN/A}
8202632Sstever@eecs.umich.edu
8211869SN/AAddrRangeList
8221884SN/AHDLcd::getAddrRanges() const
8231884SN/A{
8241884SN/A    AddrRangeList ranges;
8251884SN/A    ranges.push_back(RangeSize(pioAddr, pioSize));
8261884SN/A    return ranges;
8271884SN/A}
8281965SN/A
8291965SN/AHDLcd *
8301965SN/AHDLcdParams::create()
8312761Sstever@eecs.umich.edu{
8321869SN/A    return new HDLcd(this);
8331869SN/A}
8342632Sstever@eecs.umich.edu