| // 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.*; |
| import jnr.ffi.annotations.In; |
| import org.json.Property; |
| |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.math.BigInteger; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| |
| public class dump_bram { |
| |
| 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); |
| } |
| |
| public static void main(String[] args) throws IOException { |
| |
| File folder = new File("specimen_bram"); |
| 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()) { |
| for (PIP p : n.getPIPs()) { |
| String tile = p.getTile().getName() + ":" + p.getTile().getTileTypeEnum().toString(); |
| if (p.getTile().getTileTypeEnum() == TileTypeEnum.BRAM) |
| continue; |
| if (!pips_by_tile.containsKey(tile)) |
| pips_by_tile.put(tile, new ArrayList<>()); |
| 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.RAMB180 || si.getSiteTypeEnum() == SiteTypeEnum.RAMB181 || si.getSiteTypeEnum() == SiteTypeEnum.RAMB36) { |
| for (BEL b : si.getBELs()) { |
| String belName = b.getName(); |
| Cell c = si.getCell(b); |
| if (c == null || c.getType() == null) |
| continue; |
| if ((si.getSiteTypeEnum() == SiteTypeEnum.RAMB36 && !c.getType().equals("RAMB36E2")) || |
| ((si.getSiteTypeEnum() == SiteTypeEnum.RAMB180 || si.getSiteTypeEnum() == SiteTypeEnum.RAMB181) && !c.getType().equals("RAMB18E2"))) |
| continue; |
| int prim_width = si.getSiteTypeEnum() == SiteTypeEnum.RAMB36 ? 36 : 18; |
| tfeat.add("BRAM.IN_USE"); |
| tfeat.add(belName + ".IN_USE"); |
| boolean have_ecc = false; |
| |
| boolean is_sdp = false; |
| if (c.getProperty("READ_WIDTH_A") != null && Integer.parseInt(c.getProperty("READ_WIDTH_A").getValue()) > prim_width) |
| is_sdp = true; |
| if (c.getProperty("WRITE_WIDTH_B") != null && Integer.parseInt(c.getProperty("WRITE_WIDTH_B").getValue()) > prim_width) |
| is_sdp = true; |
| |
| String[] enum_props = { |
| "CLOCK_DOMAINS", |
| "DOA_REG", "DOB_REG", |
| "READ_WIDTH_A", "READ_WIDTH_B", "WRITE_WIDTH_A", "WRITE_WIDTH_B", |
| "WRITE_MODE_A", "WRITE_MODE_B", |
| "ENADDRENA", "ENADDRENB", "RDADDRCHANGEA", "RDADDRCHANGEB", |
| "RSTREG_PRIORITY_A", "RSTREG_PRIORITY_B", |
| "SLEEP_ASYNC", "EN_ECC_PIPE", "EN_ECC_READ", "EN_ECC_WRITE", |
| "CASCADE_ORDER_A", "CASCADE_ORDER_B"}; |
| for (String p : enum_props) { |
| EDIFPropertyValue ep = c.getProperty(p); |
| if (ep == null) |
| continue; |
| String v = ep.getValue(); |
| int base_pos = v.indexOf("'b"); |
| if (base_pos != -1) |
| v = v.substring(base_pos + 2); |
| if (p.startsWith("RSTREG_") && is_sdp) |
| continue; |
| tfeat.add(belName + "." + p + "." + v); |
| if (p.contains("EN_ECC") && v.equals("TRUE")) |
| have_ecc = true; |
| } |
| |
| var all_props = c.getProperties(); |
| for (var e : all_props.entrySet()) { |
| String name = e.getKey().getName(); |
| if (name.startsWith("IS_") && name.endsWith("_INVERTED")) { |
| String pinname = name.substring(3, name.length() - 9); |
| String v = e.getValue().getValue(); |
| int base_pos = v.indexOf("'b"); |
| if (base_pos != -1) |
| v = v.substring(base_pos + 2); |
| tfeat.add(belName + "." + pinname + "INV." + v); |
| } |
| } |
| |
| String[] word_props = {"INIT_A", "INIT_B", "SRVAL_A", "SRVAL_B"}; |
| for (String p : word_props) { |
| EDIFPropertyValue width = c.getProperty("READ_WIDTH_" + p.substring(p.length() - 1)); |
| if (width == null || !width.getValue().equals(Integer.toString(prim_width)) || have_ecc) |
| continue; |
| if (c.getProperty(p) != null) { |
| long lval = LUTTools.getInitValue(c.getProperty(p).getValue()); |
| for (int i = 0; i < prim_width; i++) { |
| if ((lval & (1L << i)) != 0) |
| tfeat.add(belName + "." + p + "[" + i + "]"); |
| } |
| } |
| } |
| for (EDIFPortInst epi : c.getEDIFCellInst().getPortInsts()) { |
| if (epi.getName().startsWith("DOUT") && epi.getNet() != null) |
| tfeat.add(belName + "." + epi.getName() + ".USED"); |
| } |
| } |
| } else if (si.getSiteTypeEnum() == SiteTypeEnum.DSP48E2) { |
| for (Cell c : si.getCells()) { |
| if (!c.getName().contains("/")) |
| continue; |
| EDIFCellInst eci = des.getTopEDIFCell().getCellInst(c.getName().split("/")[0]); |
| if (eci == null) |
| continue; |
| if (eci.getCellType().getName() != null && eci.getCellType().getName().equals("DSP48E2")) { |
| String name = site_index_in_tile(si.getTile(), si.getSite()); |
| tfeat.add("DSP.IN_USE"); |
| tfeat.add(name + ".IN_USE"); |
| boolean have_patdet = false; |
| if (eci.getProperty("USE_PATTERN_DETECT") != null && eci.getProperty("USE_PATTERN_DETECT").getValue().equals("PATDET")) |
| have_patdet = true; |
| boolean have_xor = false; |
| if (eci.getProperty("USE_WIDEXOR") != null && eci.getProperty("USE_WIDEXOR").getValue().equals("TRUE")) |
| have_xor = true; |
| |
| String[] enum_props = {"ADREG", "ALUMODEREG", "AMULTSEL", "AREG", "AUTORESET_PATDET", "AUTORESET_PRIORITY", |
| "BMULTSEL", "BREG", "CARRYINREG", "CARRYINSELREG", "CREG", "DREG", "INMODEREG", "MREG", "OPMODEREG", |
| "PREADDINSEL", "PREG", "SEL_MASK", "SEL_PATTERN", "USE_PATTERN_DETECT", "USE_SIMD", "USE_WIDEXOR", "XORSIMD"}; |
| for (String p : enum_props) { |
| EDIFPropertyValue ep = eci.getProperty(p); |
| if (ep == null) |
| continue; |
| if (!have_patdet && (p.equals("AUTORESET_PATDET") || p.equals("AUTORESET_PRIORITY") || p.equals("SEL_MASK") || p.equals("SEL_PATTERN"))) |
| continue; |
| if (!have_xor && p.equals("XORSIMD")) |
| continue; |
| String v = ep.getValue(); |
| int base_pos = v.indexOf("'b"); |
| if (base_pos != -1) |
| v = v.substring(base_pos + 2); |
| tfeat.add(name + "." + p + "." + v); |
| } |
| |
| var all_props = eci.getProperties(); |
| for (var e : all_props.entrySet()) { |
| String pname = e.getKey().getName(); |
| if (pname.startsWith("IS_") && pname.endsWith("_INVERTED")) { |
| String pinname = pname.substring(3, pname.length() - 9); |
| int width = 1; |
| if (pinname.equals("ALUMODE")) |
| width = 4; |
| else if (pinname.equals("INMODE")) |
| width = 5; |
| else if (pinname.equals("OPMODE")) |
| width = 9; |
| if (pinname.contains("RST") && (eci.getPortInst(pinname).getNet() == null || eci.getPortInst(pinname).getNet().getName().contains("const"))) |
| continue; |
| String v = e.getValue().getValue(); |
| if (width == 1) { |
| int base_pos = v.indexOf("'b"); |
| if (base_pos != -1) |
| v = v.substring(base_pos + 2); |
| tfeat.add(name + "." + pinname + "INV." + v); |
| } else { |
| long lval = LUTTools.getInitValue(v); |
| for (int i = 0; i < width; i++) { |
| tfeat.add(name + "." + pinname + "INV" + "[" + i + "]." + (((lval & (1L << i)) != 0) ? "1" : "0")); |
| } |
| } |
| |
| } |
| } |
| |
| if (/*have_patdet*/true) { |
| String[] word_props = {"MASK", "PATTERN", "RND"}; |
| for (String p : word_props) { |
| if (eci.getProperty(p) != null) { |
| long lval = LUTTools.getInitValue(eci.getProperty(p).getValue()); |
| for (int i = 0; i < 48; i++) { |
| if ((lval & (1L << i)) != 0 || (p.equals("MASK") && !have_patdet)) |
| tfeat.add(name + "." + p + "[" + i + "]"); |
| } |
| } |
| } |
| } |
| |
| for (EDIFPortInst epi : eci.getPortInsts()) { |
| if (epi.isOutput() && epi.getNet() != null) |
| tfeat.add(name + "." + epi.getName() + ".USED"); |
| } |
| |
| break; |
| } |
| } |
| |
| } |
| } |
| 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.BRAM || tt == TileTypeEnum.DSP || tt == TileTypeEnum.DSP_L || tt == TileTypeEnum.DSP_R) { |
| 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(); |
| } |
| } |
| |
| } |
| } |