#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2022 F4PGA Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
import argparse
import pickle
import re
from collections import defaultdict, namedtuple
import fasm

from f4pga.utils.quicklogic.pp3.connections import get_name_and_hop

from pathlib import Path
from f4pga.utils.quicklogic.pp3.data_structs import Loc, SwitchboxPinLoc, PinDirection, ConnectionType
from f4pga.utils.quicklogic.pp3.utils import get_quadrant_for_loc
from f4pga.utils.quicklogic.pp3.verilogmodule import VModule

from quicklogic_fasm.qlfasm import load_quicklogic_database, get_db_dir
from quicklogic_fasm.qlfasm import QL732BAssembler

Feature = namedtuple("Feature", "loc typ signature value")
RouteEntry = namedtuple("RouteEntry", "typ stage_id switch_id mux_id sel_id")
MultiLocCellMapping = namedtuple("MultiLocCellMapping", "typ fromlocset toloc pinnames")


class Fasm2Bels(object):
    """Class for parsing FASM file and producing BEL representation.

    It takes FASM lines and VPR database and converts the data to Basic
    Elements and connections between them. It allows converting this data to
    Verilog.
    """

    class Fasm2BelsException(Exception):
        """Exception for Fasm2Bels errors and unsupported features."""

        def __init__(self, message):
            self.message = message

        def __str__(self):
            return self.message

    def __init__(self, phy_db, device_name, package_name):
        """Prepares required structures for converting FASM to BELs.

        Parameters
        ----------
        phy_db: dict
            A dictionary containing cell_library, loc_map, vpr_tile_types,
            vpr_tile_grid, vpr_switchbox_types, vpr_switchbox_grid,
            connections, vpr_package_pinmaps
        """

        # load phy_db data
        self.quadrants = phy_db["phy_quadrants"]
        self.cells_library = phy_db["cells_library"]
        self.vpr_tile_types = phy_db["tile_types"]
        self.vpr_tile_grid = phy_db["phy_tile_grid"]
        self.vpr_switchbox_types = phy_db["switchbox_types"]
        self.vpr_switchbox_grid = phy_db["switchbox_grid"]
        self.connections = phy_db["connections"]

        self.device_name = device_name
        self.package_name = package_name

        self.io_to_fbio = dict()

        if self.package_name not in db["package_pinmaps"]:
            raise self.Fasm2BelsException(
                "ERROR: '{}' is not a vaild package for device '{}'. Valid ones are: {}".format(
                    self.package_name, self.device_name, ", ".join(db["package_pinmaps"].keys())
                )
            )

        for name, package in db["package_pinmaps"][self.package_name].items():
            self.io_to_fbio[package[0].loc] = name

        # Add ASSP to all locations it covers
        # TODO maybe this should be added in original vpr_tile_grid
        # set all cels in row 1 and column 2 to ASSP
        # In VPR grid, the ASSP tile is located in (1, 1)
        assplocs = set()
        ramlocs = dict()
        multlocs = dict()

        for phy_loc, tile in self.vpr_tile_grid.items():
            tile_type = self.vpr_tile_types[tile.type]
            if "ASSP" in tile_type.cells:
                assplocs.add(phy_loc)

            if "RAM" in tile_type.cells:
                ramcell = [cell for cell in tile.cells if cell.type == "RAM"]
                cellname = ramcell[0].name
                if cellname not in ramlocs:
                    ramlocs[cellname] = set()

                ramlocs[cellname].add(phy_loc)

            if "MULT" in tile_type.cells:
                multcell = [cell for cell in tile.cells if cell.type == "MULT"]
                cellname = multcell[0].name
                if cellname not in multlocs:
                    multlocs[cellname] = set()

                multlocs[cellname].add(phy_loc)

        # this map represents the mapping from input name to its inverter name
        self.inversionpins = {
            "LOGIC": {
                "TA1": "TAS1",
                "TA2": "TAS2",
                "TB1": "TBS1",
                "TB2": "TBS2",
                "BA1": "BAS1",
                "BA2": "BAS2",
                "BB1": "BBS1",
                "BB2": "BBS2",
                "QCK": "QCKS",
            }
        }

        # prepare helper structure for connections
        self.connections_by_loc = defaultdict(list)
        for connection in self.connections:
            self.connections_by_loc[connection.dst].append(connection)
            self.connections_by_loc[connection.src].append(connection)

        # a mapping from the type of cell FASM line refers to to its parser
        self.featureparsers = {
            "LOGIC": self.parse_logic_line,
            "QMUX": self.parse_logic_line,
            "GMUX": self.parse_logic_line,
            "INTERFACE": self.parse_interface_line,
            "ROUTING": self.parse_routing_line,
            "CAND0": self.parse_colclk_line,
            "CAND1": self.parse_colclk_line,
            "CAND2": self.parse_colclk_line,
            "CAND3": self.parse_colclk_line,
            "CAND4": self.parse_colclk_line,
            "RAM": self.parse_ram_line,
        }

        # a mapping from cell type to a set of possible pin names
        self.pinnames = defaultdict(set)
        for celltype in self.cells_library.values():
            typ = celltype.type
            for pin in celltype.pins:
                self.pinnames[typ].add(pin.name)

        # a mapping from cell types that occupy multiple locations
        # to a single location
        self.multiloccells = {"ASSP": MultiLocCellMapping("ASSP", assplocs, Loc(1, 1, 0), self.pinnames["ASSP"])}
        for ram in ramlocs:
            self.multiloccells[ram] = MultiLocCellMapping(
                ram, ramlocs[ram], list(ramlocs[ram])[0], self.pinnames["RAM"]
            )
        for mult in multlocs:
            self.multiloccells[mult] = MultiLocCellMapping(
                mult, multlocs[mult], list(multlocs[mult])[1], self.pinnames["MULT"]
            )

        # helper routing data
        self.routingdata = defaultdict(list)
        # a dictionary holding bit settings for BELs
        self.belinversions = defaultdict(lambda: defaultdict(list))
        # a dictionary holding bit settings for IOs
        self.interfaces = defaultdict(lambda: defaultdict(list))
        # a dictionary holding simplified connections between BELs
        self.designconnections = defaultdict(dict)
        # a dictionary holding hops from routing
        self.designhops = defaultdict(dict)

        # Clock column drivers (CAND) data
        self.colclk_data = defaultdict(lambda: defaultdict(list))
        # A map of clock wires that connect to switchboxes
        self.cand_map = defaultdict(lambda: dict())

        # A map of original (loc, pin) to new (loc, pin). Created during
        # aggregation of multi-loc cells.
        self.org_loc_map = {}

    def parse_logic_line(self, feature: Feature):
        """Parses a setting for a BEL.

        Parameters
        ----------
        feature: Feature
            FASM line for BEL
        """
        belname, setting = feature.signature.split(".", 1)
        if feature.value == 1:
            # FIXME handle ZINV pins
            if "ZINV." in setting:
                setting = setting.replace("ZINV.", "")
            elif "INV." in setting:
                setting = setting.replace("INV.", "")
            self.belinversions[feature.loc][belname].append(setting)

    def parse_interface_line(self, feature: Feature):
        """Parses a setting for IO.

        Parameters
        ----------
        feature: Feature
            FASM line for BEL
        """
        belname, setting = feature.signature.split(".", 1)
        if feature.value == 1:
            setting = setting.replace("ZINV.", "")
            setting = setting.replace("INV.", "")
            self.interfaces[feature.loc][belname].append(setting)

    def parse_routing_line(self, feature: Feature):
        """Parses a routing setting.

        Parameters
        ----------
        feature: Feature
            FASM line for BEL
        """
        match = re.match(r"^I_highway\.IM(?P<switch_id>[0-9]+)\.I_pg(?P<sel_id>[0-9]+)$", feature.signature)
        if match:
            typ = "HIGHWAY"
            stage_id = 3  # FIXME: Get HIGHWAY stage id from the switchbox def
            switch_id = int(match.group("switch_id"))
            mux_id = 0
            sel_id = int(match.group("sel_id"))
        match = re.match(
            r"^I_street\.Isb(?P<stage_id>[0-9])(?P<switch_id>[0-9])\.I_M(?P<mux_id>[0-9]+)\.I_pg(?P<sel_id>[0-9]+)$",  # noqa: E501
            feature.signature,
        )
        if match:
            typ = "STREET"
            stage_id = int(match.group("stage_id")) - 1
            switch_id = int(match.group("switch_id")) - 1
            mux_id = int(match.group("mux_id"))
            sel_id = int(match.group("sel_id"))
        self.routingdata[feature.loc].append(
            RouteEntry(typ=typ, stage_id=stage_id, switch_id=switch_id, mux_id=mux_id, sel_id=sel_id)
        )

    def parse_colclk_line(self, feature: Feature):
        self.colclk_data[feature.loc][feature.typ].append(feature)

    def parse_ram_line(self, feature: Feature):
        """Parses a RAM line.

        Parameters
        ----------
        feature: Feature
            FASM line for BEL
        """
        raise NotImplementedError("Parsing RAM FASM lines is not supported")

    def parse_fasm_lines(self, fasmlines):
        """Parses FASM lines.

        Parameters
        ----------
        fasmlines: list
            A list of FasmLine objects
        """

        loctyp = re.compile(r"^X(?P<x>[0-9]+)Y(?P<y>[0-9]+)\.(?P<type>[A-Z]+[0-4]?)\.(?P<signature>.*)$")  # noqa: E501

        for line in fasmlines:
            if not line.set_feature:
                continue
            match = loctyp.match(line.set_feature.feature)
            if not match:
                raise self.Fasm2BelsException(
                    f"FASM features have unsupported format:  {line.set_feature}"
                )  # noqa: E501
            loc = Loc(x=int(match.group("x")), y=int(match.group("y")), z=0)
            typ = match.group("type")
            feature = Feature(loc=loc, typ=typ, signature=match.group("signature"), value=line.set_feature.value)
            self.featureparsers[typ](feature)

    def decode_switchbox(self, switchbox, features):
        """Decodes all switchboxes to extract full connections' info.

        For every output, this method determines its input in the routing
        switchboxes. In this representation, an input and output can be either
        directly connected to a BEL, or to a hop wire.

        Parameters
        ----------
        switchbox: a Switchbox object from vpr_switchbox_types
        features: features regarding given switchbox

        Returns
        -------
        dict: a mapping from output pin to input pin for a given switchbox
        """
        # Group switchbox connections by destinationa
        conn_by_dst = defaultdict(set)
        for c in switchbox.connections:
            conn_by_dst[c.dst].add(c)

        # Prepare data structure
        mux_sel = {}
        for stage_id, stage in switchbox.stages.items():
            mux_sel[stage_id] = {}
            for switch_id, switch in stage.switches.items():
                mux_sel[stage_id][switch_id] = {}
                for mux_id, mux in switch.muxes.items():
                    mux_sel[stage_id][switch_id][mux_id] = None

        for feature in features:
            assert mux_sel[feature.stage_id][feature.switch_id][feature.mux_id] is None, feature  # noqa: E501
            mux_sel[feature.stage_id][feature.switch_id][feature.mux_id] = feature.sel_id  # noqa: E501

        def expand_mux(out_loc):
            """
            Expands a multiplexer output until a switchbox input is reached.
            Returns name of the input or None if not found.

            Parameters
            ----------
            out_loc: the last output location

            Returns
            -------
            str: None if input name not found, else string
            """

            # Get mux selection, If it is set to None then the mux is
            # not active
            sel = mux_sel[out_loc.stage_id][out_loc.switch_id][out_loc.mux_id]
            if sel is None:
                return None  # TODO can we return None?

            stage = switchbox.stages[out_loc.stage_id]
            switch = stage.switches[out_loc.switch_id]
            mux = switch.muxes[out_loc.mux_id]
            pin = mux.inputs[sel]

            if pin.name is not None:
                return pin.name

            inp_loc = SwitchboxPinLoc(
                stage_id=out_loc.stage_id,
                switch_id=out_loc.switch_id,
                mux_id=out_loc.mux_id,
                pin_id=sel,
                pin_direction=PinDirection.INPUT,
            )

            # Expand all "upstream" muxes that connect to the selected
            # input pin
            assert inp_loc in conn_by_dst, inp_loc
            for c in conn_by_dst[inp_loc]:
                inp = expand_mux(c.src)
                if inp is not None:
                    return inp

            # Nothing found
            return None  # TODO can we return None?

        # For each output pin of a switchbox determine to which input is it
        # connected to.
        routes = {}
        for out_pin in switchbox.outputs.values():
            out_loc = out_pin.locs[0]
            routes[out_pin.name] = expand_mux(out_loc)

        return routes

    def process_switchbox(self, loc, switchbox, features):
        """Processes all switchboxes and extract hops from connections.

        The function extracts final connections from inputs to outputs, and
        hops into separate structures for further processing.

        Parameters
        ----------
        loc: Loc
            location of the current switchbox
        switchbox: Switchbox
            a switchbox
        features: list
            list of features regarding given switchbox
        """
        routes = self.decode_switchbox(switchbox, features)
        for k, v in routes.items():
            if v is not None:
                if re.match("[VH][0-9][LRBT][0-9]", k):
                    self.designhops[Loc(loc.x, loc.y, 0)][k] = v
                else:
                    self.designconnections[loc][k] = v

    def resolve_hops(self):
        """Resolves remaining hop wires.

        It determines the absolute input for the given pin by resolving hop
        wires and adds those final connections to the design connections.
        """
        for loc, conns in self.designconnections.items():
            for pin, source in conns.items():
                hop = get_name_and_hop(source)
                tloc = loc
                while hop[1] is not None:
                    tloc = Loc(tloc[0] + hop[1][0], tloc[1] + hop[1][1], 0)
                    # in some cases BEL is distanced from a switchbox, in those
                    # cases the hop will not point to another hop. We should
                    # simply return the pin here in the correct location
                    if hop[0] in self.designhops[tloc]:
                        hop = get_name_and_hop(self.designhops[tloc][hop[0]])
                    else:
                        hop = (hop[0], None)
                self.designconnections[loc][pin] = (tloc, hop[0])

    def resolve_connections(self):
        """Resolves connections between BELs and IOs."""
        keys = sorted(self.routingdata.keys(), key=lambda loc: (loc.x, loc.y))
        for loc in keys:
            routingfeatures = self.routingdata[loc]

            if loc in self.vpr_switchbox_grid:
                typ = self.vpr_switchbox_grid[loc]
                switchbox = self.vpr_switchbox_types[typ]
                self.process_switchbox(loc, switchbox, routingfeatures)
        self.resolve_hops()

    def remap_multiloc_loc(self, loc, pinname=None, celltype=None):
        """Unifies coordinates of cells occupying multiple locations.

        Some cells, like ASSP, RAM or multipliers occupy multiple locations.
        This method groups bits and connections for those cells into a single
        artificial location.

        Parameters
        ----------
        loc: Loc
            The current location
        pinname: str
            The optional name of the pin (used to determine to which cell
            pin refers to)
        celltype: str
            The optional name of the cell type

        Returns
        -------
        Loc: the new location of the cell
        """
        finloc = loc
        for multiloc in self.multiloccells.values():
            if pinname is None or pinname in multiloc.pinnames or celltype == multiloc.typ:
                if loc in multiloc.fromlocset:
                    finloc = multiloc.toloc
                    break
        return finloc

    def resolve_multiloc_cells(self):
        """Groups cells that are scattered around multiple locations."""
        newbelinversions = defaultdict(lambda: defaultdict(list))
        newdesignconnections = defaultdict(dict)

        for bellockey, bellocpair in self.belinversions.items():
            for belloctype, belloc in bellocpair.items():
                if belloctype in self.multiloccells:
                    newbelinversions[self.remap_multiloc_loc(bellockey, celltype=belloctype)][belloctype].extend(belloc)
        self.belinversion = newbelinversions

        for loc, conns in self.designconnections.items():
            for pin, src in conns.items():
                dstloc = self.remap_multiloc_loc(loc, pinname=pin)
                srcloc = self.remap_multiloc_loc(src[0], pinname=src[1])

                if srcloc != src[0]:
                    k, v = ((srcloc, src[1]), src)
                    if k in self.org_loc_map:
                        assert v == self.org_loc_map[k], (k, self.org_loc_map[k], v)
                    self.org_loc_map[k] = v

                if dstloc != loc:
                    k, v = ((dstloc, pin), (loc, pin))
                    if k in self.org_loc_map:
                        assert v == self.org_loc_map[k], (k, self.org_loc_map[k], v)
                    self.org_loc_map[k] = v

                newdesignconnections[dstloc][pin] = (srcloc, src[1])
        self.designconnections = newdesignconnections

    def get_clock_for_gmux(self, gmux, loc):
        """Returns location of a CLOCK cell associated with the given GMUX
        cell. Returns None if not found

        Parameters
        ----------
        gmux: str
            The GMUX cell name
        loc: Loc
            The GMUX location

        Returns
        -------
        Loc: the new location of the cell or None
        """

        connections = [
            c for c in self.connections if c.src.type == ConnectionType.TILE and c.dst.type == ConnectionType.TILE
        ]
        for connection in connections:
            # Only to a GMUX at the given location
            dst = connection.dst
            if dst.loc != loc or "GMUX" not in dst.pin:
                continue

            # GMUX cells are named "GMUX<index>".
            cell, pin = dst.pin.split("_", maxsplit=1)
            match = re.match(r"GMUX(?P<idx>[0-9]+)", cell)
            if match is None:
                continue

            # Not the cell that we are looking for
            if cell != gmux:
                continue

            # We are only interested in the IP connection
            if pin != "IP":
                continue

            # Must go from CLOCK<n>.IC pin
            cell, pin = connection.src.pin.split("_", maxsplit=1)
            if not cell.startswith("CLOCK") or pin != "IC":
                continue

            # Return the source location
            return connection.src.loc

        # Not found
        return None

    def get_gmux_for_qmux(self, qmux, loc):
        """Returns a map of the given QMUX selection to driving GMUX cells.

        Parameters
        ----------
        qmux: str
            The QMUX cell name
        loc: Loc
            The QMUX location

        Returns
        -------
        Dict: A dict indexed by the selection index holding tuples with format:
            (loc, cell, pin)
        """

        sel_map = {}

        connections = [c for c in self.connections if c.dst.type == ConnectionType.CLOCK]
        for connection in connections:
            # Only to a QMUX at the given location
            dst = connection.dst
            if dst.loc != loc or "QMUX" not in dst.pin:
                continue

            # QMUX cells are named "QMUX_<quad><index>".
            cell, pin = dst.pin.split(".", maxsplit=1)
            match = re.match(r"QMUX_(?P<quad>[A-Z]+)(?P<idx>[0-9]+)", cell)
            if match is None:
                continue

            # This is not for the given QMUX
            qmux_idx = int(match.group("idx"))
            if qmux != "QMUX{}".format(qmux_idx):
                continue

            # Get the QCLKIN pin index. These are named "QCLKIN<index>"
            match = re.match(r"QCLKIN(?P<idx>[0-9]+)", pin)
            if match is None:
                continue
            qclkin_idx = int(match.group("idx"))

            # Get the source endpoint of the connection
            cell, pin = connection.src.pin.split("_", maxsplit=1)
            match = re.match(r"GMUX(?P<idx>[0-9]+)", cell)
            if match is None:
                continue
            gmux_idx = int(match.group("idx"))

            # Since fasm2bels uses physical database, it is not aware of
            # other QMUX inputs that QCLKIN0. Assume that the connection
            # found is to the QCLKIN0 pin and add QCLKIN1..2 to the map
            # as well.
            assert qclkin_idx == 0, connection

            # Make map entries
            for i in range(3):
                # Calculate GMUX index for QCLKIN<i> input of the QMUX
                idx = (gmux_idx + i) % 5

                # Add to the map
                sel_map[i] = (
                    connection.src.loc,
                    "GMUX{}".format(idx),
                    pin,
                )

        return sel_map

    def get_qmux_for_cand(self, cand, loc):
        """Returns a QMUX cell and its location that drives the given CAND
        cell.

        Parameters
        ----------
        cand: str
            The CAND cell name
        loc: Loc
            The CAND location

        Returns
        -------
        Tuple: A tuple holding (loc, cell)
        """

        connections = [c for c in self.connections if c.dst.type == ConnectionType.CLOCK]
        for connection in connections:
            # Only to a CAND at the given location
            # Note: Check also the row above. CAND cells are located in two
            # rows but with fasm features everything gets aligned to even rows
            dst = connection.dst
            if (dst.loc != loc and dst.loc != Loc(loc.x, loc.y - 1, loc.z)) or "CAND" not in dst.pin:
                continue

            # CAND cells are named "CAND<index>_<quad>_<column>".
            cell, pin = dst.pin.split(".", maxsplit=1)
            match = re.match(r"CAND(?P<idx>[0-9]+)_(?P<quad>[A-Z]+)_(?P<col>[0-9]+)", cell)
            if match is None:
                continue

            # This is not for the given CAND
            if cand != "CAND{}".format(match.group("idx")):
                continue

            # QMUX cells are named "QMUX_<quad><index>".
            cell, pin = connection.src.pin.split(".", maxsplit=1)
            match = re.match(r"QMUX_(?P<quad>[A-Z]+)(?P<idx>[0-9]+)", cell)
            if match is None:
                continue

            # Return the QMUX and its location
            return "QMUX{}".format(match.group("idx")), connection.src.loc

        # None found
        return None, None

    def resolve_gmux(self):
        """Resolves GMUX cells, updates the designconnections map. Also creates
        connections to CLOCK cells whenever necessary.

        Returns
        -------
        Dict: A map of GMUX names to their output wires
        """

        # Process GMUX
        gmux_map = dict()
        gmux_locs = [loc for loc, tile in self.vpr_tile_grid.items() if "GMUX" in tile.type]
        for loc in gmux_locs:
            # Group GMUX input pin connections by GMUX cell names
            gmux_connections = defaultdict(lambda: dict())
            for cell_pin, conn in self.designconnections[loc].items():
                if cell_pin.startswith("GMUX"):
                    cell, pin = cell_pin.split("_", maxsplit=1)
                    gmux_connections[cell][pin] = conn

            # Examine each GMUX config
            for gmux, connections in gmux_connections.items():
                # FIXME: Handle IS0 inversion (if any)

                # The IS0 pin has to be routed
                if "IS0" not in connections:
                    print("WARNING: Pin '{}.IS0' at '{}' is unrouted!".format(gmux, loc))
                    continue

                # TODO: For now support only static GMUX settings
                if connections["IS0"][1] not in ["GND", "VCC"]:
                    print("WARNING: Non-static GMUX selection (at '{}') not supported yet!".format(loc))
                    continue

                # Static selection
                sel = int(connections["IS0"][1] == "VCC")

                # IP selected
                if sel == 0:
                    # Create a global clock wire for the CLOCK pad
                    match = re.match(r"GMUX(?P<idx>[0-9]+)", gmux)
                    assert match is not None, gmux

                    idx = int(match.group("idx"))
                    wire = "CLK{}".format(idx)

                    # Get the clock pad location
                    clock_loc = self.get_clock_for_gmux(gmux, loc)
                    assert clock_loc is not None, gmux

                    # Check if the clock pad is enabled. If not then discard
                    # the GMUX
                    bel_features = []
                    for bel, features in self.interfaces.get(clock_loc, {}).items():
                        for feature in features:
                            bel_features.append("{}.{}".format(bel, feature))

                    if "ASSP.ASSPInvPortAlias" not in bel_features:
                        continue

                    # Connect it to the output wire of the GMUX
                    self.designconnections[clock_loc]["CLOCK0_IC"] = (None, wire)

                    # The GMUX is implicit. Remove all connections to it
                    self.designconnections[loc] = {
                        k: v for k, v in self.designconnections[loc].items() if not k.startswith(gmux)
                    }

                # IC selected
                else:
                    # Check if the IC pin has an active driver. If not then
                    # discard the mux.
                    if connections.get("IC", (None, None))[1] in [None, "GND", "VCC"]:
                        continue

                    # Create a wire for the GMUX output
                    wire = "{}_X{}Y{}".format(gmux, loc.x, loc.y)

                    # Remove the IS0 connection
                    del self.designconnections[loc]["{}_IS0".format(gmux)]

                    # Connect the output
                    self.designconnections[loc]["{}_IZ".format(gmux)] = (None, wire)

                # Store the wire
                gmux_map[gmux] = wire

        return gmux_map

    def resolve_qmux(self, gmux_map):
        """Resolves QMUX cells, updates the designconnections map.

        Parameters
        ----------
        gmux_map: Dict
            A map of QMUX cells to their GMUX driving wires.

        Returns
        -------
        Dict: A map of locations and QMUX names to their driving wires
        """

        # Process QMUX
        qmux_map = defaultdict(lambda: dict())
        qmux_locs = [loc for loc, tile in self.vpr_tile_grid.items() if "QMUX" in tile.type]
        for loc in qmux_locs:
            # Group QMUX input pin connections by QMUX cell names
            qmux_connections = defaultdict(lambda: dict())
            for cell_pin, conn in self.designconnections[loc].items():
                if cell_pin.startswith("QMUX"):
                    cell, pin = cell_pin.split("_", maxsplit=1)
                    qmux_connections[cell][pin] = conn

            # Examine each QMUX config
            for qmux, connections in qmux_connections.items():
                # FIXME: Handle IS0 and IS1 inversion (if any)

                # Both IS0 and IS1 must be routed to something
                if "IS0" not in connections:
                    print("WARNING: Pin '{}.IS0' at '{}' is unrouted!".format(qmux, loc))
                if "IS1" not in connections:
                    print("WARNING: Pin '{}.IS1' at '{}' is unrouted!".format(qmux, loc))

                if "IS0" not in connections or "IS1" not in connections:
                    continue

                # TODO: For now support only static QMUX settings
                if connections["IS0"][1] not in ["GND", "VCC"]:
                    print("WARNING: Non-static QMUX selection (at '{}') not supported yet!".format(loc))
                    continue
                if connections["IS1"][1] not in ["GND", "VCC"]:
                    print("WARNING: Non-static QMUX selection (at '{}') not supported yet!".format(loc))
                    continue

                # Get associated GMUXes
                sel_map = self.get_gmux_for_qmux(qmux, loc)

                # Static selection
                sel = int(connections["IS0"][1] == "VCC") * 2 + int(connections["IS1"][1] == "VCC")

                # Input from the routing network selected, create a new wire
                if sel == 3:
                    # Check if the HSCKIN input is connected to an active
                    # driver. If not then discard the QMUX
                    if connections.get("HSCKIN", (None, None))[1] in [None, "GND", "VCC"]:
                        continue

                    # Create a wire for the QMUX output
                    wire = "{}_X{}Y{}".format(qmux, loc.x, loc.y)

                    # Remove IS0 and IS1 from the connection map.
                    del self.designconnections[loc]["{}_IS0".format(qmux)]
                    del self.designconnections[loc]["{}_IS1".format(qmux)]

                    # Connect the output
                    self.designconnections[loc]["{}_IZ".format(qmux)] = (None, wire)

                # Input from a GMUX is selected, assign its wire here
                else:
                    # The GMUX is not active. Discard the QMUX
                    gmux_loc, gmux_cell, gmux_pin = sel_map[sel]
                    if gmux_cell not in gmux_map:
                        continue

                    # Use the wire of that GMUX
                    wire = gmux_map[gmux_cell]

                    # The QMUX is implicit. Remove all connections to it
                    self.designconnections[loc] = {
                        k: v for k, v in self.designconnections[loc].items() if not k.startswith(qmux)
                    }

                # Store the wire
                qmux_map[loc][qmux] = wire

        return dict(qmux_map)

    def resolve_cand(self, qmux_map):
        """Resolves CAND cells, creates the cand_map map.

        Parameters
        ----------
        qmux_map: Dict
            A map of locations and CAND names to their driving QMUXes.

        Returns
        -------
        None
        """

        # Process CAND
        for loc, all_features in self.colclk_data.items():
            for cand, features in all_features.items():
                hilojoint = False
                enjoint = False

                for feature in features:
                    if feature.signature == "I_hilojoint":
                        hilojoint = bool(feature.value)
                    if feature.signature == "I_enjoint":
                        enjoint = bool(feature.value)

                # TODO: Do not support dynamically enabled CANDs for now.
                assert enjoint is False, "Dynamically enabled CANDs are not supported yet"

                # Statically disabled, skip this one
                if hilojoint is False:
                    continue

                # Find a QMUX driving this CAND cell
                qmux_cell, qmux_loc = self.get_qmux_for_cand(cand, loc)
                assert qmux_cell is not None, (cand, loc)

                # The QMUX is not active, skip this one
                if qmux_loc not in qmux_map:
                    continue

                # Get the wire
                wire = qmux_map[qmux_loc][qmux_cell]

                # Populate the column clock to switchbox connection map
                quadrant = get_quadrant_for_loc(loc, self.quadrants)
                for y in range(quadrant.y0, quadrant.y1 + 1):
                    sb_loc = Loc(loc.x, y, 0)
                    self.cand_map[sb_loc][cand] = wire

    def resolve_global_clock_network(self):
        """Resolves the global clock network. Creates the cand_map, updates
        the designconnections.

        Returns
        -------
        None
        """

        # Resolve GMUXes
        gmux_map = self.resolve_gmux()
        # Resolve QMUXes
        qmux_map = self.resolve_qmux(gmux_map)
        # Resolve CANDs
        self.resolve_cand(qmux_map)

    def produce_verilog(self, pcf_data):
        """Produces string containing Verilog module representing FASM.

        Returns
        -------
        str, str: a Verilog module and PCF
        """

        module = VModule(
            self.vpr_tile_grid,
            self.vpr_tile_types,
            self.cells_library,
            pcf_data,
            self.belinversions,
            self.interfaces,
            self.designconnections,
            self.org_loc_map,
            self.cand_map,
            self.inversionpins,
            self.io_to_fbio,
        )
        module.parse_bels()
        verilog = module.generate_verilog()
        pcf = module.generate_pcf()
        qcf = module.generate_qcf()
        return verilog, pcf, qcf

    def convert_to_verilog(self, fasmlines):
        """Runs all methods required to convert FASM lines to Verilog module.

        Parameters
        ----------
        fasmlines: list
            FASM lines to process

        Returns
        -------
        str: a Verilog module
        """
        self.parse_fasm_lines(fasmlines)
        self.resolve_connections()
        self.resolve_multiloc_cells()
        self.resolve_global_clock_network()
        verilog, pcf, qcf = self.produce_verilog(pcf_data)
        return verilog, pcf, qcf


def parse_pcf(pcf):
    pcf_data = {}
    with open(pcf, "r") as fp:
        for line in fp:
            line = line.strip().split()
            if len(line) < 3:
                continue
            if len(line) > 3 and not line[3].startswith("#"):
                continue
            if line[0] != "set_io":
                continue
            pcf_data[line[2]] = line[1]
    return pcf_data


if __name__ == "__main__":
    # Parse arguments
    parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)

    parser.add_argument("input_file", type=Path, help="Input fasm file")

    parser.add_argument("--phy-db", type=str, required=True, help="Physical device database file")

    parser.add_argument("--device-name", type=str, required=True, choices=["eos-s3", "pp3e"], help="Device name")

    parser.add_argument("--package-name", type=str, required=True, help="Device package name")

    parser.add_argument(
        "--input-type",
        type=str,
        choices=["bitstream", "fasm"],
        default="fasm",
        help="Determines whether the input is a FASM file or bitstream",
    )

    parser.add_argument("--output-verilog", type=Path, required=True, help="Output Verilog file")
    parser.add_argument(
        "--input-pcf", type=Path, required=False, help="Pins constraint file to maintain original pin names"
    )

    parser.add_argument("--output-pcf", type=Path, help="Output PCF file")
    parser.add_argument("--output-qcf", type=Path, help="Output QCF file")

    args = parser.parse_args()

    pcf_data = {}
    if args.input_pcf is not None:
        pcf_data = parse_pcf(args.input_pcf)

    # Load data from the database
    with open(args.phy_db, "rb") as fp:
        db = pickle.load(fp)

    # Initialize fasm2bels
    f2b = Fasm2Bels(db, args.device_name, args.package_name)

    # Disassemble bitstream / load FASM
    if args.input_type == "bitstream":
        qlfasmdb = load_quicklogic_database(get_db_dir("ql-" + args.device_name))

        if args.device_name == "eos-s3":
            assembler = QL732BAssembler(qlfasmdb)
        elif args.device_name == "pp3e":
            assembler = QL732BAssembler(qlfasmdb)  # Workaround: use EOS-S3 assembler for PP3E
        else:
            assert False, args.device_name

        assembler.read_bitstream(args.input_file)
        fasmlines = assembler.disassemble()
        fasmlines = [line for line in fasm.parse_fasm_string("\n".join(fasmlines))]

    else:
        fasmlines = [line for line in fasm.parse_fasm_filename(args.input_file)]

    # Run fasm2bels
    verilog, pcf, qcf = f2b.convert_to_verilog(fasmlines)

    # Write output files
    with open(args.output_verilog, "w") as outv:
        outv.write(verilog)

    if args.output_pcf:
        with open(args.output_pcf, "w") as outpcf:
            outpcf.write(pcf)
    if args.output_qcf:
        with open(args.output_qcf, "w") as outqcf:
            outqcf.write(qcf)
