// Copyright 2020 Project U-Ray 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.

package dev.fpga.rapidwright;

import com.xilinx.rapidwright.design.*;
import com.xilinx.rapidwright.design.tools.LUTTools;
import com.xilinx.rapidwright.device.*;
import com.xilinx.rapidwright.edif.EDIFPortInst;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;

public class dump_clocking {
    static String site_index_in_tile(Tile t, Site s) {
        int min_x = s.getInstanceX(), min_y = s.getInstanceY();
        for (Site s2 : t.getSites()) {
            if (s2.getSiteTypeEnum() == s.getSiteTypeEnum()) {
                min_x = Math.min(min_x, s2.getInstanceX());
                min_y = Math.min(min_y, s2.getInstanceY());
            }
        }
        return s.getSiteTypeEnum().toString() + "_X" + (s.getInstanceX() - min_x) + "Y" + (s.getInstanceY() - min_y);
    }

    static HashSet<String> inverted_pips = new HashSet<>();

    static boolean is_sink_inverted(SitePinInst spi) {
        if (spi == null || spi.getNet() == null)
            return false;
        Net n = spi.getNet();
        HashMap<Node, PIP> pip_uphill = new HashMap<>();
        for (PIP p : n.getPIPs()) {
            pip_uphill.putIfAbsent(p.getEndNode(), p);
            if (p.isBidirectional()) {
                pip_uphill.putIfAbsent(p.getStartNode(), p);
            }
        }
        boolean inv = false;
        Node cursor = spi.getConnectedNode();
        while (pip_uphill.containsKey(cursor)) {
            PIP p = pip_uphill.get(cursor);
            String name = p.getTile().getName() + "/" + p.getTile().getTileTypeEnum().toString() + "." + p.getStartWireName() + (p.isBidirectional() ? "<<->>" : "->>") + p.getEndWireName();
            if (inverted_pips.contains(name))
                inv = !inv;
            //System.out.println(name + " " + inv);
            if (p.isBidirectional() && p.getStartNode().equals(cursor))
                cursor = p.getEndNode();
            else
                cursor = p.getStartNode();
        }
        return inv;
    }

    public static void main(String[] args) throws IOException {


        Scanner scanner = new Scanner(new File("/invpips.txt"));
        while (scanner.hasNextLine()) {
            String nl = scanner.nextLine().trim();
            inverted_pips.add(nl);
        }

        File folder = new File("/specimen_clk");
        File[] listOfFiles = folder.listFiles();
        for (File f : listOfFiles) {
            if (f.getName().endsWith(".dcp")) {
                Design des = Design.readCheckpoint(f.getAbsolutePath());
                HashMap<String, ArrayList<String>> pips_by_tile = new HashMap<>();
                HashMap<String, ArrayList<String>> sitefeatures_by_tile = new HashMap<>();
                for (Net n : des.getNets()) {

                    HashMap<Node, PIP> uphill = new HashMap<>();
                    HashSet<Node> allnodes = new HashSet<>();

                    if (n.getSource() != null)
                        uphill.put(n.getSource().getConnectedNode(), null);
                    for (PIP p : n.getPIPs()) {
                        if (!p.isBidirectional()) {
                            uphill.put(p.getEndNode(), p);
                        }

                        allnodes.add(p.getStartNode());
                        allnodes.add(p.getEndNode());

                        TileTypeEnum ptt = p.getTile().getTileTypeEnum();
                        if (ptt == TileTypeEnum.RCLK_INT_L || ptt == TileTypeEnum.RCLK_INT_R) {
                            if (p.getEndWireName().startsWith("CLK_LEAF_SITES_") && p.getEndWireName().endsWith("_CLK_LEAF")) {
                                String tile = p.getTile().getName() + ":" + p.getTile().getTileTypeEnum().toString();
                                if (!pips_by_tile.containsKey(tile))
                                    pips_by_tile.put(tile, new ArrayList<>());
                                pips_by_tile.get(tile).add("WIRE." + p.getEndWireName() + ".DRIVEN");
                                if (p.getStartWireName().endsWith("_CLK_IN") && p.isRouteThru()) {
                                    String site = site_index_in_tile(p.getTile(), p.getStartNode().getSitePin().getSite());
                                    if (!sitefeatures_by_tile.containsKey(tile))
                                        sitefeatures_by_tile.put(tile, new ArrayList<>());
                                    sitefeatures_by_tile.get(tile).add(site + ".BUFCE_LEAF.IN_USE");
                                }
                            }
                        }
                    }

                    for (Node node : allnodes) {
                        for (Wire w : node.getAllWiresInNode()) {
                            TileTypeEnum wtt = w.getTile().getTileTypeEnum();
                            if (wtt == TileTypeEnum.RCLK_BRAM_INTF_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_TD_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_TD_R ||
                                    wtt == TileTypeEnum.RCLK_CLEL_L_L || wtt == TileTypeEnum.RCLK_CLEL_L || wtt == TileTypeEnum.RCLK_CLEL_L_R ||
                                    wtt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || wtt == TileTypeEnum.RCLK_CLEM_L || wtt == TileTypeEnum.RCLK_DSP_INTF_L ||
                                    wtt == TileTypeEnum.RCLK_CLEM_R || wtt == TileTypeEnum.RCLK_CLEL_R) {
                                if (w.getWireName().startsWith("CLK_TEST_BUF_SITE_") || w.getWireName().startsWith("CLK_HROUTE_CORE_OPT")) {
                                    String tile = w.getTile().getName() + ":" + w.getTile().getTileTypeEnum().toString();
                                    if (!pips_by_tile.containsKey(tile))
                                        pips_by_tile.put(tile, new ArrayList<>());
                                    pips_by_tile.get(tile).add("WIRE." + w.getWireName() + ".USED");

                                }
                            }
                            if (wtt == TileTypeEnum.RCLK_DSP_INTF_CLKBUF_L || wtt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || wtt == TileTypeEnum.RCLK_BRAM_INTF_L) {
                                if (w.getWireName().startsWith("CLK_HROUTE") || w.getWireName().startsWith("CLK_HDISTR")) {
                                    String tile = w.getTile().getName() + ":" + w.getTile().getTileTypeEnum().toString();
                                    if (!pips_by_tile.containsKey(tile))
                                        pips_by_tile.put(tile, new ArrayList<>());
                                    pips_by_tile.get(tile).add("WIRE." + w.getWireName() + ".USED");
                                }
                            }
                            if (wtt == TileTypeEnum.CMT_L) {
                                //CLK_HROUTE_
                                if (w.getWireName().startsWith("CLK_HROUTE_") || w.getWireName().startsWith("CLK_HDISTR_") || w.getWireName().startsWith("CLK_VDISTR_") ||
                                        w.getWireName().startsWith("CLK_TEST_BUF_SITE_")) {
                                    String tile = w.getTile().getName() + ":" + w.getTile().getTileTypeEnum().toString();
                                    if (!pips_by_tile.containsKey(tile))
                                        pips_by_tile.put(tile, new ArrayList<>());
                                    pips_by_tile.get(tile).add("WIRE." + w.getWireName() + ".USED");
                                }
                            }
                        }
                    }

                    for (PIP p : n.getPIPs()) {

                        String tile = p.getTile().getName() + ":" + p.getTile().getTileTypeEnum().toString();
                        if (p.getTile().getTileTypeEnum() == TileTypeEnum.BRAM || p.getTile().getTileTypeEnum() == TileTypeEnum.INT)
                            continue;
                        if (!pips_by_tile.containsKey(tile))
                            pips_by_tile.put(tile, new ArrayList<>());
                        if (p.isBidirectional()) {
                            Node cursor = p.getStartNode();
                            boolean is_fwd = false;
                            if (uphill.containsKey(p.getStartNode())) {
                                is_fwd = true;
                                uphill.put(p.getEndNode(), p);
                            } else if (uphill.containsKey(p.getEndNode())) {
                                is_fwd = false;
                                uphill.put(p.getStartNode(), p);
                            } else {
                                continue;
                            }
                            pips_by_tile.get(tile).add("PIP." + p.getEndWireName() + "." + p.getStartWireName() + (is_fwd ? ".FWD" : ".REV"));
                        } else {
                            pips_by_tile.get(tile).add("PIP." + p.getEndWireName() + "." + p.getStartWireName());
                        }
                    }
                }
                for (SiteInst si : des.getSiteInsts()) {
                    String tile = si.getTile().getName() + ":" + si.getTile().getTileTypeEnum().toString();
                    if (!sitefeatures_by_tile.containsKey(tile))
                        sitefeatures_by_tile.put(tile, new ArrayList<>());
                    ArrayList<String> tfeat = sitefeatures_by_tile.get(tile);
                    if (si.getSiteTypeEnum() == SiteTypeEnum.BUFCE_LEAF) {
                        String name = site_index_in_tile(si.getTile(), si.getSite());
                        for (Cell c : si.getCells()) {
                            if (c.getType() != null && c.getType().equals("BUFCE_LEAF")) {
                                tfeat.add(name + ".BUFCE_LEAF.IN_USE");
                                if (c.getProperty("CE_TYPE") != null)
                                    tfeat.add(name + ".BUFCE_LEAF.CE_TYPE." + c.getProperty("CE_TYPE").getValue());
                                var all_props = c.getProperties();
                                for (var e : all_props.entrySet()) {
                                    String propname = e.getKey().getName();
                                    if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
                                        String pinname = propname.substring(3, propname.length() - 9);
                                        String v = e.getValue().getValue();
                                        int base_pos = v.indexOf("'b");
                                        if (base_pos != -1)
                                            v = v.substring(base_pos + 2);
                                        if (pinname.equals("I"))
                                            if (is_sink_inverted(si.getSitePinInst("CLK_IN")))
                                                v = (v.equals("1") ? "0" : "1");
                                        tfeat.add(name + ".BUFCE_LEAF." + pinname + "INV." + v);
                                    }
                                }
                            }
                        }
                    } else if (si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE || si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE_DIV) {
                        String name = site_index_in_tile(si.getTile(), si.getSite());
                        for (Cell c : si.getCells()) {
                            if (c.getType() != null && c.getType().startsWith("BUFGCE")) {
                                tfeat.add(name + "." + c.getType() + ".IN_USE");
                                var all_props = c.getProperties();
                                for (var e : all_props.entrySet()) {
                                    String propname = e.getKey().getName();
                                    String v = e.getValue().getValue();
                                    int base_pos = v.indexOf("'b");
                                    if (base_pos != -1)
                                        v = v.substring(base_pos + 2);
                                    if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
                                        String pinname = propname.substring(3, propname.length() - 9);
                                        if (pinname.equals("I"))
                                            if (is_sink_inverted(si.getSitePinInst("CLK_IN")))
                                                v = (v.equals("1") ? "0" : "1");
                                        tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
                                    } else if ((si.getSiteTypeEnum() == SiteTypeEnum.BUFGCE && propname.equals("CE_TYPE")) || propname.equals("BUFGCE_DIVIDE")) {
                                        tfeat.add(name +  "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
                                    }
                                }
                            }
                        }
                    } else if (si.getSiteTypeEnum() == SiteTypeEnum.BUFGCTRL) {
                        String name = site_index_in_tile(si.getTile(), si.getSite());
                        for (Cell c : si.getCells()) {
                            if (c.getType() != null && c.getType().startsWith("BUFGCTRL")) {
                                tfeat.add(name + "." + c.getType() + ".IN_USE");
                                var all_props = c.getProperties();
                                for (var e : all_props.entrySet()) {
                                    String propname = e.getKey().getName();
                                    String v = e.getValue().getValue();
                                    int base_pos = v.indexOf("'b");
                                    if (base_pos != -1)
                                        v = v.substring(base_pos + 2);
                                    if (propname.startsWith("IS_") && propname.endsWith("_INVERTED")) {
                                        String pinname = propname.substring(3, propname.length() - 9);
                                        if (pinname.equals("I0") || pinname.equals("I1"))
                                            if (is_sink_inverted(si.getSitePinInst("CLK_" + pinname)))
                                                v = (v.equals("1") ? "0" : "1");
                                        tfeat.add(name + "." + si.getSiteTypeEnum().toString() + "." + pinname + "INV." + v);
                                    } else if (propname.equals("INIT_OUT") || propname.startsWith("PRESELECT_")) {
                                        tfeat.add(name +  "." + si.getSiteTypeEnum().toString() + "." + propname + "." + v);
                                    }
                                }
                            }
                        }
                    }
                }
                FileWriter vf = new FileWriter(f.getAbsolutePath().replace(".dcp", ".features"), false);
                PrintWriter v = new PrintWriter(vf);
                for (Tile t : des.getDevice().getAllTiles()) {
                    TileTypeEnum tt = t.getTileTypeEnum();
                    if (tt == TileTypeEnum.RCLK_INT_L|| tt == TileTypeEnum.RCLK_CLEM_L || tt == TileTypeEnum.RCLK_INT_R || tt == TileTypeEnum.RCLK_CLEM_CLKBUF_L || tt == TileTypeEnum.RCLK_CLEM_R ||
                            tt == TileTypeEnum.RCLK_DSP_INTF_L || tt == TileTypeEnum.RCLK_BRAM_L || tt == TileTypeEnum.RCLK_BRAM_R || tt == TileTypeEnum.RCLK_BRAM_INTF_L ||
                            tt == TileTypeEnum.RCLK_CLEL_L || tt == TileTypeEnum.RCLK_CLEL_R || tt == TileTypeEnum.RCLK_CLEL_L_L || tt == TileTypeEnum.RCLK_CLEL_L_R ||
                            tt == TileTypeEnum.RCLK_DSP_INTF_CLKBUF_L || tt == TileTypeEnum.RCLK_BRAM_INTF_TD_L || tt == TileTypeEnum.RCLK_BRAM_INTF_TD_R || tt == TileTypeEnum.CMT_L || tt == TileTypeEnum.CMT_RIGHT) {
                        String tname = t.getName() + ":" + tt.toString();
                        if (!pips_by_tile.containsKey(tname) && !sitefeatures_by_tile.containsKey(tname))
                            continue;
                        v.println(".tile " + tname);
                        if (pips_by_tile.containsKey(tname))
                            for (String p : pips_by_tile.get(tname))
                                v.println(p);
                        if (sitefeatures_by_tile.containsKey(tname))
                            for (String sf : sitefeatures_by_tile.get(tname))
                                v.println(sf);
                    }
                }
                vf.close();
            }
        }

    }
}
