aboutsummaryrefslogtreecommitdiffstats
path: root/common/sdf.cc
blob: 5c3d0a5a7c1aeb8e5db83fb653a40166bc48da45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
From efb984b47e685c966a3b55874de2c1fb5b0b1140 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Mon, 14 Jul 2014 22:02:09 +0100
Subject: [PATCH 069/232] hid: Reduce default mouse polling interval to 60Hz

Reduces overhead when using X
---
 drivers/hid/usbhid/hid-core.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -49,7 +49,7 @@
  * Module parameters.
  */
 
-static unsigned int hid_mousepoll_interval;
+static unsigned int hid_mousepoll_interval = ~0;
 module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
 MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
 
@@ -1091,8 +1091,12 @@ static int usbhid_start(struct hid_devic
 		}
 
 		/* Change the polling interval of mice. */
-		if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
-			interval = hid_mousepoll_interval;
+		if (hid->collection->usage == HID_GD_MOUSE) {
+				if (hid_mousepoll_interval == ~0 && interval < 16)
+						interval = 16;
+				else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0)
+						interval = hid_mousepoll_interval;
+		}
 
 		ret = -ENOMEM;
 		if (usb_endpoint_dir_in(endpoint)) {
332 333 334
/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2019  David Shah <dave@ds0.me>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "nextpnr.h"
#include "util.h"

NEXTPNR_NAMESPACE_BEGIN

namespace SDF {

struct MinMaxTyp
{
    double min, typ, max;
};

struct RiseFallDelay
{
    MinMaxTyp rise, fall;
};

struct PortAndEdge
{
    std::string port;
    ClockEdge edge;
};

struct IOPath
{
    std::string from, to;
    RiseFallDelay delay;
};

struct TimingCheck
{
    enum CheckType
    {
        SETUPHOLD,
        PERIOD,
        WIDTH
    } type;
    PortAndEdge from, to;
    RiseFallDelay delay;
};

struct Cell
{
    std::string celltype, instance;
    std::vector<IOPath> iopaths;
    std::vector<TimingCheck> checks;
};

struct CellPort
{
    std::string cell, port;
};

struct Interconnect
{
    CellPort from, to;
    RiseFallDelay delay;
};

struct SDFWriter
{
    bool cvc_mode = false;
    std::vector<Cell> cells;
    std::vector<Interconnect> conn;
    std::string sdfversion, design, vendor, program;

    std::string format_name(const std::string &name)
    {
        std::string fmt = "\"";
        for (char c : name) {
            if (c == '\\' || c == '\"')
                fmt += "\"";
            fmt += c;
        }
        fmt += "\"";
        return fmt;
    }

    std::string escape_name(const std::string &name)
    {
        std::string esc;
        for (char c : name) {
            if (c == '$' || c == '\\' || c == '[' || c == ']' || c == ':' || (cvc_mode && c == '.'))
                esc += '\\';
            esc += c;
        }
        return esc;
    }

    std::string timing_check_name(TimingCheck::CheckType type)
    {
        switch (type) {
        case TimingCheck::SETUPHOLD:
            return "SETUPHOLD";
        case TimingCheck::PERIOD:
            return "PERIOD";
        case TimingCheck::WIDTH:
            return "WIDTH";
        default:
            NPNR_ASSERT_FALSE("unknown timing check type");
        }
    }

    void write_delay(std::ostream &out, const RiseFallDelay &delay)
    {
        write_delay(out, delay.rise);
        out << " ";
        write_delay(out, delay.fall);
    }

    void write_delay(std::ostream &out, const MinMaxTyp &delay)
    {
        if (cvc_mode)
            out << "(" << int(delay.min) << ":" << int(delay.typ) << ":" << int(delay.max) << ")";
        else
            out << "(" << delay.min << ":" << delay.typ << ":" << delay.max << ")";
    }

    void write_port(std::ostream &out, const CellPort &port)
    {
        if (cvc_mode)
            out << escape_name(port.cell) + "." + escape_name(port.port);
        else
            out << escape_name(port.cell + "/" + port.port);
    }

    void write_portedge(std::ostream &out, const PortAndEdge &pe)
    {
        out << "(" << (pe.edge == RISING_EDGE ? "posedge" : "negedge") << " " << escape_name(pe.port) << ")";
    }

    void write(std::ostream &out)
    {
        out << "(DELAYFILE" << std::endl;
        // Headers and  metadata
        out << "  (SDFVERSION " << format_name(sdfversion) << ")" << std::endl;
        out << "  (DESIGN " << format_name(design) << ")" << std::endl;
        out << "  (VENDOR " << format_name(vendor) << ")" << std::endl;
        out << "  (PROGRAM " << format_name(program) << ")" << std::endl;
        out << "  (DIVIDER " << (cvc_mode ? "." : "/") << ")" << std::endl;
        out << "  (TIMESCALE 1ps)" << std::endl;
        // Write interconnect delays, with the main design begin a "cell"
        out << "  (CELL" << std::endl;
        out << "    (CELLTYPE " << format_name(design) << ")" << std::endl;
        out << "    (INSTANCE )" << std::endl;
        out << "    (DELAY" << std::endl;
        out << "      (ABSOLUTE" << std::endl;
        for (auto &ic : conn) {
            out << "        (INTERCONNECT ";
            write_port(out, ic.from);
            out << " ";
            write_port(out, ic.to);
            out << " ";
            write_delay(out, ic.delay);
            out << ")" << std::endl;
        }
        out << "      )" << std::endl;
        out << "    )" << std::endl;
        out << "  )" << std::endl;
        // Write cells
        for (auto &cell : cells) {
            out << "  (CELL" << std::endl;
            out << "    (CELLTYPE " << format_name(cell.celltype) << ")" << std::endl;
            out << "    (INSTANCE " << escape_name(cell.instance) << ")" << std::endl;
            // IOPATHs (combinational delay and clock-to-q)
            if (!cell.iopaths.empty()) {
                out << "    (DELAY" << std::endl;
                out << "      (ABSOLUTE" << std::endl;
                for (auto &path : cell.iopaths) {
                    out << "        (IOPATH " << escape_name(path.from) << " " << escape_name(path.to) << " ";
                    write_delay(out, path.delay);
                    out << ")" << std::endl;
                }
                out << "      )" << std::endl;
                out << "    )" << std::endl;
            }
            // Timing Checks (setup/hold, period, width)
            if (!cell.checks.empty()) {
                out << "    (TIMINGCHECK" << std::endl;
                for (auto &check : cell.checks) {
                    out << "      (" << timing_check_name(check.type) << " ";
                    write_portedge(out, check.from);
                    out << " ";
                    if (check.type == TimingCheck::SETUPHOLD) {
                        write_portedge(out, check.to);
                        out << " ";
                    }
                    if (check.type == TimingCheck::SETUPHOLD)
                        write_delay(out, check.delay);
                    else
                        write_delay(out, check.delay.rise);
                    out << ")" << std::endl;
                }
                out << "    )" << std::endl;
            }
            out << "    )" << std::endl;
        }
        out << ")" << std::endl;
    }
};

} // namespace SDF

void Context::writeSDF(std::ostream &out, bool cvc_mode) const
{
    using namespace SDF;
    SDFWriter wr;
    wr.cvc_mode = cvc_mode;
    wr.design = str_or_default(attrs, id("module"), "top");
    wr.sdfversion = "3.0";
    wr.vendor = "nextpnr";
    wr.program = "nextpnr";

    const double delay_scale = 1000;
    // Convert from DelayQuad to SDF-friendly RiseFallDelay
    auto convert_delay = [&](const DelayQuad &dly) {
        RiseFallDelay rf;
        rf.rise.min = getDelayNS(dly.minRiseDelay()) * delay_scale;
        rf.rise.typ = getDelayNS((dly.minRiseDelay() + dly.maxRiseDelay()) / 2) * delay_scale; // fixme: typ delays?
        rf.rise.max = getDelayNS(dly.maxRiseDelay()) * delay_scale;
        rf.fall.min = getDelayNS(dly.minFallDelay()) * delay_scale;
        rf.fall.typ = getDelayNS((dly.minFallDelay() + dly.maxFallDelay()) / 2) * delay_scale; // fixme: typ delays?
        rf.fall.max = getDelayNS(dly.maxFallDelay()) * delay_scale;
        return rf;
    };

    auto convert_setuphold = [&](const DelayPair &setup, const DelayPair &hold) {
        RiseFallDelay rf;
        rf.rise.min = getDelayNS(setup.minDelay()) * delay_scale;
        rf.rise.typ = getDelayNS((setup.minDelay() + setup.maxDelay()) / 2) * delay_scale; // fixme: typ delays?
        rf.rise.max = getDelayNS(setup.maxDelay()) * delay_scale;
        rf.fall.min = getDelayNS(hold.minDelay()) * delay_scale;
        rf.fall.typ = getDelayNS((hold.minDelay() + hold.maxDelay()) / 2) * delay_scale; // fixme: typ delays?
        rf.fall.max = getDelayNS(hold.maxDelay()) * delay_scale;
        return rf;
    };

    for (auto cell : sorted(cells)) {
        Cell sc;
        const CellInfo *ci = cell.second;
        sc.instance = ci->name.str(this);
        sc.celltype = ci->type.str(this);
        for (auto port : ci->ports) {
            int clockCount = 0;
            TimingPortClass cls = getPortTimingClass(ci, port.first, clockCount);
            if (cls == TMG_IGNORE)
                continue;
            if (port.second.net == nullptr)
                continue; // Ignore disconnected ports
            if (port.second.type != PORT_IN) {
                // Add combinational paths to this output (or inout)
                for (auto other : ci->ports) {
                    if (other.second.net == nullptr)
                        continue;
                    if (other.second.type == PORT_OUT)
                        continue;
                    DelayQuad dly;
                    if (!getCellDelay(ci, other.first, port.first, dly))
                        continue;
                    IOPath iop;
                    iop.from = other.first.str(this);
                    iop.to = port.first.str(this);
                    iop.delay = convert_delay(dly);
                    sc.iopaths.push_back(iop);
                }
                // Add clock-to-output delays, also as IOPaths
                if (cls == TMG_REGISTER_OUTPUT)
                    for (int i = 0; i < clockCount; i++) {
                        auto clkInfo = getPortClockingInfo(ci, port.first, i);
                        IOPath cqp;
                        cqp.from = clkInfo.clock_port.str(this);
                        cqp.to = port.first.str(this);
                        cqp.delay = convert_delay(clkInfo.clockToQ);
                        sc.iopaths.push_back(cqp);
                    }
            }
            if (port.second.type != PORT_OUT && cls == TMG_REGISTER_INPUT) {
                // Add setup/hold checks
                for (int i = 0; i < clockCount; i++) {
                    auto clkInfo = getPortClockingInfo(ci, port.first, i);
                    TimingCheck chk;
                    chk.from.edge = RISING_EDGE; // Add setup/hold checks equally for rising and falling edges
                    chk.from.port = port.first.str(this);
                    chk.to.edge = clkInfo.edge;
                    chk.to.port = clkInfo.clock_port.str(this);
                    chk.type = TimingCheck::SETUPHOLD;
                    chk.delay = convert_setuphold(clkInfo.setup, clkInfo.hold);
                    sc.checks.push_back(chk);
                    chk.from.edge = FALLING_EDGE;
                    sc.checks.push_back(chk);
                }
            }
        }
        wr.cells.push_back(sc);
    }

    for (auto net : sorted(nets)) {
        NetInfo *ni = net.second;
        if (ni->driver.cell == nullptr)
            continue;
        for (auto &usr : ni->users) {
            Interconnect ic;
            ic.from.cell = ni->driver.cell->name.str(this);
            ic.from.port = ni->driver.port.str(this);
            ic.to.cell = usr.cell->name.str(this);
            ic.to.port = usr.port.str(this);
            // FIXME: min/max routing delay
            ic.delay = convert_delay(DelayQuad(getNetinfoRouteDelay(ni, usr)));
            wr.conn.push_back(ic);
        }
    }
    wr.write(out);
}

NEXTPNR_NAMESPACE_END