Xilinx / RapidWright

Build Customized FPGA Implementations for Vivado
http://www.rapidwright.io
Other
286 stars 109 forks source link

Pin map conflicts with a LUT5-LUT6 pair. #750

Closed haydenc-amd closed 1 year ago

haydenc-amd commented 1 year ago

I am attempting to import a placed design into RapidWright and create a new "cloned" circuit that contains the same placed cells and nets. The imported design has a few placed LUT5-LUT6 pairs. However, when creating and placing the cells, the pins mappings are incompatible. Specifically, I get an exception when trying to connect the physical nets to the cells placed on the LUT5-LUT6 pair (see code below).

While I could just copy over the pin mappings, it would be much nicer, my overall application is a RapidWright code generator that takes a checkpoint and generates RapidWright code to build the circuit. I want to make the generated code seem as human-written as possible, and providing a compatible pin-mapping for a LUT5-LUT6 pair doesn't seem like something an average RapidWright user could do.

It would be nice to be able to have the Net.connect() function remap the pins of the cells in the pair if a conflict occurs. If that is too difficult, I could connect the logical nets first, then call a function to remap all the pins of the LUT5-LUT6 pairs, then create the physical nets from the logical ones.

Here's the checkpoint and the code that throws the error.

Checkpoint (unzip for .edf and .dcp): stoplightController.zip

Code:

package com.xilinx.rapidwright.llm;

import com.xilinx.rapidwright.design.Cell;
import com.xilinx.rapidwright.design.Design;
import com.xilinx.rapidwright.design.Net;
import com.xilinx.rapidwright.design.NetType;
import com.xilinx.rapidwright.design.PinType;
import com.xilinx.rapidwright.design.Unisim;
import com.xilinx.rapidwright.device.Package;
import com.xilinx.rapidwright.device.PackagePin;
import com.xilinx.rapidwright.device.Site;
import com.xilinx.rapidwright.edif.EDIFCell;
import com.xilinx.rapidwright.edif.EDIFCellInst;
import com.xilinx.rapidwright.edif.EDIFNet;
import com.xilinx.rapidwright.edif.EDIFNetlist;
import com.xilinx.rapidwright.edif.EDIFPort;
import com.xilinx.rapidwright.edif.EDIFPortInst;
import com.xilinx.rapidwright.edif.EDIFPropertyValue;
import com.xilinx.rapidwright.edif.EDIFTools;

import java.util.HashMap;
import java.util.Map;

public class stoplightClone {
    final static String TEST_DESIGN = "stoplightController.dcp";
    static public void main(String[] args) {
        Design testDesign = Design.readCheckpoint(TEST_DESIGN, TEST_DESIGN.replace(".dcp", ".edf"));
        EDIFNetlist testNetlist = testDesign.getNetlist();
        EDIFCell testTop = testNetlist.getTopCell();

        Design d = new Design(testDesign.getName(), testDesign.getPartName());
        EDIFNetlist netlist = d.getNetlist();
        EDIFCell top = netlist.getTopCell();

        for(Cell cell : testDesign.getCells()) {
            if (!cell.isPlaced()) continue;
            if (cell.getSiteType().toString().contains("IOB")) continue;

            Cell newCell = d.createAndPlaceCell(cell.getName(), Unisim.valueOf(cell.getType()), cell.getSite().getName() + "/" + cell.getBELName());
            Map<String, EDIFPropertyValue> properties = cell.getProperties();
            for (String key : properties.keySet()) {
                String value = properties.get(key).toString();
                newCell.addProperty(key, value);
            }
        }

        HashMap<String, String> siteToPinNameMap = new HashMap<>();
        Package pkg = testDesign.getDevice().getActivePackage();
        for (PackagePin pin : pkg.getPackagePinMap().values()) {
            Site site = pin.getSite();
            if (site == null) continue;
            siteToPinNameMap.put(pin.getSite().getName(), pin.getName());
        }

        for(EDIFPort port : testTop.getPorts()) {
            PinType pinType = port.isOutput() ? PinType.OUT : PinType.IN;
            Cell cell = testDesign.getCell(port.getName());
            String pinName = siteToPinNameMap.get(cell.getSiteName());
            String ioStandard = "LVCMOS"+cell.getSiteType().toString().substring(3, 5);

             Cell iob = d.createAndPlaceIOB(port.getName(), pinType, pinName, ioStandard);
        }

        EDIFNet testGnd = EDIFTools.getStaticNet(NetType.GND, testTop, testNetlist);
        EDIFNet testVcc = EDIFTools.getStaticNet(NetType.VCC, testTop, testNetlist);
        for(EDIFNet edifNet : testTop.getNets()) {
            if (edifNet.equals(testGnd) || edifNet.equals(testVcc)) continue;
            if (top.getNet(edifNet.getName()) != null) continue; // Net already exists (probably from creating the IOB)
            Net net = d.createNet(edifNet.getName());
            System.out.println(net);

            for(EDIFPortInst port : edifNet.getPortInsts()) {
                String cellName = port.getCellInst().getName();
                if (cellName.endsWith("BUF_inst")) {
                    cellName = cellName.substring(0,cellName.length()-10);
                }
                Cell cell = d.getCell(cellName);
                net.connect(cell, port.getName());
            }
        }

        d.writeCheckpoint("stoplightController.clone.dcp");
    }
}
haydenc-amd commented 1 year ago

This issue is complex and impossible to solve without having a finalized logical netlist. Closing for now.