Skip to content

Conversation

@reillymck
Copy link
Contributor

Related to my issue #1228, I was tracing backwards from the sinks of the LUT constant generator in the static site. I wanted to use DesignTools.getConnectionPips() as a way to trace back to the SitePinInst of the driving site. This function failed as the biDir list is null and the current pip in the iteraction does not equal the source node of the global constant net. I assume in general this function will fail for SitePinInsts that are driven by LUT constant generators. I added some code to fix this.

@reillymck reillymck changed the title Fix getConnectionPips for sinks driven by lut constant generators Fix DesignTools.getConnectionPips for sinks driven by lut constant generators Jun 21, 2025
@clavin-xlnx
Copy link
Member

Thanks @reillymck, will take a look next week.

@eddieh-xlnx
Copy link
Collaborator

Hi @reillymck. Thanks for your contribution! Can you build a test or share a testcase which exhibits the problem that you are solving here please?

As an example, the test for bidir PIPs here:

@Test
public void testGetConnectionPIPsBiDir() {
Design design = new Design("cw305_top", "xc7a100tftg256-2");
Device device = design.getDevice();
Net net = com.xilinx.rapidwright.util.CodeGenerator.createTestNet(design, "net", new String[] {
"CLBLM_L_X26Y155/CLBLM_L.CLBLM_L_BQ->CLBLM_LOGIC_OUTS1", "INT_L_X26Y155/INT_L.LOGIC_OUTS_L1->>IMUX_L11",
"CLBLM_L_X26Y155/CLBLM_L.CLBLM_IMUX11->CLBLM_M_A4", "INT_L_X26Y155/INT_L.LOGIC_OUTS_L1->>IMUX_L27",
"CLBLM_L_X26Y155/CLBLM_L.CLBLM_IMUX27->CLBLM_M_B4", "INT_L_X26Y155/INT_L.LOGIC_OUTS_L1->>SR1BEG2",
"INT_L_X26Y154/INT_L.SR1END2->>ER1BEG3", "INT_R_X27Y154/INT_R.ER1END3->>LH0",
"INT_R_X15Y154/INT_R.LV0<<->>LH12", "INT_R_X15Y172/INT_R.LV18->>NE6BEG3",
"INT_R_X17Y176/INT_R.NE6END3->>SL1BEG3", "INT_R_X17Y175/INT_R.SL1END3->>IMUX22",
"CLBLL_R_X17Y175/CLBLL_R.CLBLL_IMUX22->CLBLL_LL_C3", "INT_L_X26Y155/INT_L.LOGIC_OUTS_L1->>NN6BEG1",
"INT_L_X26Y161/INT_L.NN6END1->>NW6BEG1", "INT_L_X24Y165/INT_L.NW6END1->>NW6BEG1",
"INT_L_X22Y169/INT_L.NW6END1->>NW6BEG1", "INT_L_X20Y173/INT_L.NW6END1->>WW2BEG0",
"INT_L_X18Y173/INT_L.WW2END0->>NW2BEG1", "INT_R_X17Y174/INT_R.NW2END1->>IMUX42",
"CLBLL_R_X17Y174/CLBLL_R.CLBLL_IMUX42->CLBLL_L_D6", "INT_L_X18Y173/INT_L.WW2END0->>WR1BEG2",
"INT_R_X17Y173/INT_R.WR1END2->>IMUX13", "CLBLL_R_X17Y173/CLBLL_R.CLBLL_IMUX13->CLBLL_L_B6",
"INT_R_X17Y173/INT_R.WR1END2->>NW2BEG2", "INT_L_X16Y174/INT_L.NW2END2->>NL1BEG1",
"INT_L_X16Y175/INT_L.NL1END1->>IMUX_L26", "CLBLL_L_X16Y175/CLBLL_L.CLBLL_IMUX26->CLBLL_L_B4",
"INT_L_X16Y174/INT_L.NW2END2->>IMUX_L20", "CLBLL_L_X16Y174/CLBLL_L.CLBLL_IMUX20->CLBLL_L_C2",
"INT_L_X20Y173/INT_L.NW6END1->>NW2BEG1", "INT_R_X19Y174/INT_R.NW2END1->>FAN_ALT2",
"INT_R_X19Y174/INT_R.FAN_ALT2->>FAN_BOUNCE2", "INT_R_X19Y174/INT_R.FAN_BOUNCE2->>IMUX0",
"CLBLL_R_X19Y174/CLBLL_R.CLBLL_IMUX0->CLBLL_L_A3", "INT_R_X19Y174/INT_R.NW2END1->>IMUX33",
"CLBLL_R_X19Y174/CLBLL_R.CLBLL_IMUX33->CLBLL_L_C1", "INT_R_X19Y174/INT_R.NW2END1->>IMUX41",
"CLBLL_R_X19Y174/CLBLL_R.CLBLL_IMUX41->CLBLL_L_D1" });
SiteInst si1 = design.createSiteInst(device.getSite("SLICE_X43Y155"));
net.createPin("BQ", si1);
SiteInst si2 = design.createSiteInst(device.getSite("SLICE_X26Y175"));
net.createPin("C3", si2);
List<PIP> pips = DesignTools.getConnectionPIPs(si2.getSitePinInst("C3"));
Assertions.assertNotNull(pips);
Assertions.assertEquals(9, pips.size());
}

Also, wouldn't this affect all nets that don't have bidir PIPs, rather than just static nets?

@reillymck
Copy link
Contributor Author

Hey @eddieh-xlnx, thanks for the feedback. Also, sorry for the delayed response.
What is happening is there is a LUT with no inputs and an equation "O6=1" driving the clk pin of another site. The FFs on that site are configured as LCDEs to be used as routethrus (the CLKINV BEL flips the signal as it enters the site). So when you query the net that is driving the CLK site pin, it shows up as GLOBAL_LOGIC1. However, if you follow the path of the pips on the connection, it brings you to the LUT's site. The reason this breaks getConnectionPIPs, is because the function initializes the source pip by calling Net..getSource().getConnectedNode().
To answer your question about nets that do not have bidir pips, the function as it stands in the main branch is already able to handle these. This is because the reverseNodeToPIPMap will keep returning pips without any problems until it reaches the source pip. However, with my constant generator signal, it never reaches the source pip that is located after the global constant tieoff. Instead, it runs out of pips (because it has reached the true source pip). The current assumption that the function makes is that reverseNodeToPIPMap only returns null when a bidirectional pip exists in the path. So in my case, it tries to iterate an empty bidirectional pip list which throws an exception. The only other case that I can think of where it may try to iterate an empty list is if there is a broken net with a pip missing for some reason. In that case, I think the function should still fail, which is why I have the check that net is indeed a constant net.
I'm not quite sure how to replicate this "organic" Vivado design I have using the testing tools, but here is the design checkpoint with a script that will raise an exception if you run it on the code in main vs returning a list of correct pips if you run it on my branch.
test_getConnectionPips.zip

@reillymck
Copy link
Contributor Author

@eddieh-xlnx I was wondering what I needed to do to get this merged in. Do I need to add a full test case in TestDesignTools?

@eddieh-xlnx
Copy link
Collaborator

Sorry that I haven't gotten to this. A test would certainly help me understand what the problem you're trying to solve is. It would be good to extract the relevant subtree from the relevant net of the DCP using https://github.com/Xilinx/RapidWright/blob/master/src/com/xilinx/rapidwright/util/CodeGenerator.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants