diff --git a/src/com/xilinx/rapidwright/design/blocks/PBlockGenerator.java b/src/com/xilinx/rapidwright/design/blocks/PBlockGenerator.java index 32075980c..90579db76 100644 --- a/src/com/xilinx/rapidwright/design/blocks/PBlockGenerator.java +++ b/src/com/xilinx/rapidwright/design/blocks/PBlockGenerator.java @@ -942,14 +942,14 @@ public ArrayList generatePBlockFromReport(String reportFileName, String } sb.append("SLICE_X" + upperLeft.getInstanceX() + "Y" + (upperLeft.getInstanceY()-(numSLICERows-1)) + ":SLICE_X" + (upperLeft.getInstanceX()+(numSLICEColumns+numSLICEMColumns)-1) + "Y" + upperLeft.getInstanceY()); - } + } if(numBRAMColumns > 0){ int pIdx = 0; for(int i=0; pIdx < p.size(); i++){ TileTypeEnum t = dev.getTile(row, col+i).getTileTypeEnum(); if(Utils.isBRAM(t)){ for(Site s : dev.getTile(row, col+i).getSites()){ - if(s.getSiteTypeEnum() == SiteTypeEnum.RAMBFIFO36) upperLeft = s; + if((s.getSiteTypeEnum() == SiteTypeEnum.RAMBFIFO36)||(s.getSiteTypeEnum() == SiteTypeEnum.RAMBFIFO36E1)) upperLeft = s; // Update. Goal: support for 7 series } break; } diff --git a/src/com/xilinx/rapidwright/placer/blockplacer/BlockPlacer2.java b/src/com/xilinx/rapidwright/placer/blockplacer/BlockPlacer2.java index 906c3ad42..e7cc59d2a 100644 --- a/src/com/xilinx/rapidwright/placer/blockplacer/BlockPlacer2.java +++ b/src/com/xilinx/rapidwright/placer/blockplacer/BlockPlacer2.java @@ -97,6 +97,9 @@ public class BlockPlacer2 { private String inputXPNFileName; private double alpha; private double beta; + + // Update. Added variable to support partial .dcp + public boolean save_partial_dcp = true; /** * Empty Constructor @@ -602,6 +605,8 @@ public Design placeDesign(Design design, boolean debugFlow){ Arrays.sort(array); HashSet usedTiles = new HashSet(); + // Added variable for genreating partial dcp + boolean save_and_exit = false; // Perform final placement of all hard macros for(HardMacro hm : array){ //System.out.println(moveCount.get(hm) + " " + hm.tileSize + " " + hm.getName()); @@ -610,13 +615,25 @@ public Design placeDesign(Design design, boolean debugFlow){ if(!placeModuleNear((ModuleInst)hm, hm.getTempAnchorSite().getTile(), usedTiles)){ System.out.println("Saving as debug."); - MessageGenerator.briefErrorAndExit("ERROR: Placement failed, couldn't find valid site for " + hm.getName()); + // Updated code. Goal: if placement fails, unplace that IP and generate .dcp in order to let vivado continue PAR + if(save_partial_dcp) { + save_and_exit = true; + System.out.println("ERROR: Placement failed for "+hm.getName()); + hm.unplace(); + } else + MessageGenerator.briefErrorAndExit("ERROR: Placement failed, couldn't find valid site for " + hm.getName()); } } else{ usedTiles.addAll(footPrint); if(!hm.place(hm.getTempAnchorSite())){ - MessageGenerator.briefErrorAndExit("ERROR: Problem placing " + hm.getName() + " on site: " + hm.getTempAnchorSite()); + // Updated code. Goal: if placement fails, unplace that IP and generate .dcp in order to let vivado continue PAR + if(save_partial_dcp) { + save_and_exit = true; + System.out.println("ERROR: Placement failed for "+hm.getName()); + hm.unplace(); + } else + MessageGenerator.briefErrorAndExit("ERROR: Problem placing " + hm.getName() + " on site: " + hm.getTempAnchorSite()); } } } @@ -626,6 +643,13 @@ public Design placeDesign(Design design, boolean debugFlow){ i.place(i.getSite()); } + // Updated code. Goal: if placement fails, unplace that IP and generate .dcp in order to let vivado continue PAR + if(save_and_exit) { + String placedDCPName = "partialy_placed.dcp"; + design.writeCheckpoint(placedDCPName); + MessageGenerator.briefErrorAndExit("ERROR: Placement failed, couldn't find valid site for all the IPs. Partially placed .dcp saved for debug " ); + } + return design; } @@ -838,7 +862,9 @@ private boolean getNextMove(HardMacro selected){ } } - + // Updated code. Store initial number of valid Sites + int nr_valid_sites = validSiteRange.size(); + int rand_site = 0; while(true){ /*if(iterations > 10*validSites.size()){ selected = hardMacros.get(rand.nextInt(hardMacros.size()-1)); @@ -847,17 +873,19 @@ private boolean getNextMove(HardMacro selected){ hm0 = selected; iterations = 0; }*/ - if(iterations > hardMacros.size()*validSiteRange.size()){ - return false; + if(iterations >= nr_valid_sites){ // Updated code. Maximum trial nr = nr valid Sites + return false; } iterations++; //site1 = validSites.get(rand.nextInt(validSites.size()-1)); if (validSiteRange.size()> 0){ if (validSiteRange.size()>1){ - site1 = validSiteRange.get(rand.nextInt(validSiteRange.size()-1)); + rand_site = rand.nextInt(validSiteRange.size()-1); + site1 = validSiteRange.get(rand_site); }else{ //site1 = validSiteRange.get(rand.nextInt(validSiteRange.size())); + rand_site = 0; site1 = validSiteRange.get(0); } }else{ @@ -865,7 +893,8 @@ private boolean getNextMove(HardMacro selected){ } if(site0.equals(site1)) { //if(DEBUG_LEVEL > 1) System.out.println(" SAME SITE"); - continue; + validSiteRange.remove(rand_site); // Updated code. Remove sites that were already checked + continue; } hm1 = currentPlacements.get(site1); @@ -876,7 +905,8 @@ private boolean getNextMove(HardMacro selected){ hm1.setTempAnchorSite(site1, currentPlacements); hm0.setTempAnchorSite(site0, currentPlacements); //if(DEBUG_LEVEL > 1) System.out.println(" BAD SWAP"); - continue; + validSiteRange.remove(rand_site); // Updated code. Remove sites that were already checked + continue; } //System.out.println(hm0.getName()+"<->"+hm1.getName()); break; @@ -886,13 +916,14 @@ private boolean getNextMove(HardMacro selected){ if(!checkValidPlacement(hm0)){ hm0.setTempAnchorSite(site0, currentPlacements); //if(DEBUG_LEVEL > 1) System.out.println(" BAD SITE0"); - continue; + validSiteRange.remove(rand_site); // Updated code. Remove sites that were already checked + continue; } //System.out.println(hm0.getName()+"-> EMPTY"); break; } } - currentMove.setMove(site0, site1, hm0, hm1); + currentMove.setMove(site0, site1, hm0, hm1); return true; } diff --git a/tcl/rapidwright.tcl b/tcl/rapidwright.tcl index 7170c1be6..b084dccd9 100755 --- a/tcl/rapidwright.tcl +++ b/tcl/rapidwright.tcl @@ -53,7 +53,9 @@ proc compile_block_dcp { dcpFile } { puts "RAPIDWRIGHT_PATH=$rwpath" puts "CLASSPATH=$cpath" exec java com.xilinx.rapidwright.util.Unzip ${dcpFile} ${unzipDir} - read_xdc ${unzipDir}/${rootDcpFileName}_in_context.xdc + # Avoid naming problems caused by the fact that the files copied into IP_CACHE have different names as the ones expected by RW. Error appears only in designs with multiple IPs with the same ID + set file_name_xdc [glob -directory ${unzipDir} *_in_context.xdc] + read_xdc $file_name_xdc file delete -force ${unzipDir} # END Work around @@ -394,6 +396,10 @@ proc prep_for_block_stitcher {} { puts "WILL RUN: $ip_run $name $ip $id $ip_cell" } } elseif { [needs_impl_run $cachePath $ip] && ![info exists uniqueImplIPs($id)] } { + # Goal: avoid errors caused by IP names (in case of multiple IPs, files copied into the IP_CACHE might have different names as RW expects. Possible explanation = RW reads IPs in this loop in a different order as it copies the .dcps already generated by vivado ) + if {[get_uniq_ip_name $cachePath $ip]!="none"} { + set ip [get_uniq_ip_name $cachePath $ip] + } puts "OPT RUN: $ip" lappend opt_runs_needed $ip set uniqueImplIPs($id) $ip @@ -662,3 +668,24 @@ proc offset_dsps { count } { puts "Moving $c from $s to $new_site" } } + + +# Get name of ip based on the name of the files copied into the directory with the corresponding ID. Useful for designs using multiple IPs, in order to avoid naming errors after copying files into the IP_CACHE +proc get_uniq_ip_name {cachePath ip} { + set cache_id [config_ip_cache -get_id $ip] + set cacheIPDir "${cachePath}[cache_version_dir]/$cache_id" + if { ! [file exists $cacheIPDir] } { + puts "ERROR! No IP in this folder" + return "none" + } + set existingIP [lindex [get_lines_matching instanceName ${cacheIPDir}/${cache_id}.xci] 0] + set existingIP [string map {"" ""} $existingIP] + set existingIP [string map {"" ""} $existingIP] + set existingIP [string trim $existingIP] + set ip_return [get_ips $existingIP] + if {$ip_return!={}} { + return $ip_return + } else { + return $ip + } +}