import argparse
import pickle
import re
from collections import defaultdict, namedtuple
import fasm

from connections import get_name_and_hop

from pathlib import Path
from data_structs import Loc, SwitchboxPinLoc, PinDirection, ConnectionType
from utils import get_quadrant_for_loc
from 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)
