diff --git a/himbaechel/uarch/gatemate/CMakeLists.txt b/himbaechel/uarch/gatemate/CMakeLists.txt index b5f61388..19ba8436 100644 --- a/himbaechel/uarch/gatemate/CMakeLists.txt +++ b/himbaechel/uarch/gatemate/CMakeLists.txt @@ -5,6 +5,7 @@ set(SOURCES config.cc config.h constids.inc + delay.cc extra_data.h gatemate.cc gatemate.h diff --git a/himbaechel/uarch/gatemate/constids.inc b/himbaechel/uarch/gatemate/constids.inc index 960965fa..024e068f 100644 --- a/himbaechel/uarch/gatemate/constids.inc +++ b/himbaechel/uarch/gatemate/constids.inc @@ -2283,3 +2283,716 @@ X(L2T4_UPPER) X(CPE_MX8) X(CPE_BRIDGE) X(MULT_INVERT) + +// Timing +X(timing_ADDF2x_IN5_8_comb2) +X(timing_CIN_C_CINI) +X(timing_CIN_C_IN4) +X(timing_CINX_IN4) +X(timing__ARBLUT_CINX_OUT1) +X(timing__ARBLUT_CINX_OUT2) +X(timing_CPOUT_cpout) +X(timing_LUT2A_LUT2B) +X(timing_PINX_IN8) +X(timing__ARBLUT_PINX_OUT1) +X(timing__ARBLUT_PINX_OUT2) +X(timing_PINY1_IN2_6) +X(timing__ARBLUT_PINY1_OUT1) +X(timing__ARBLUT_PINY1_OUT2) +X(timing_Q1_OUT1) +X(timing_Q2_OUT2) +X(timing_RAM_ECC_IOPATH_1) +X(timing_RAM_ECC_IOPATH_2) +X(timing_RAM_ECC_IOPATH_3) +X(timing_RAM_ECC_IOPATH_4) +X(timing_RAM_ECC_SETUPHOLD_1) +X(timing_RAM_ECC_SETUPHOLD_10) +X(timing_RAM_ECC_SETUPHOLD_2) +X(timing_RAM_ECC_SETUPHOLD_3) +X(timing_RAM_ECC_SETUPHOLD_4) +X(timing_RAM_ECC_SETUPHOLD_5) +X(timing_RAM_ECC_SETUPHOLD_6) +X(timing_RAM_ECC_SETUPHOLD_7) +X(timing_RAM_ECC_SETUPHOLD_8) +X(timing_RAM_ECC_SETUPHOLD_9) +X(timing_RAM_ECC_WIDTH) +X(timing_RAM_NOECC_IOPATH_1) +X(timing_RAM_NOECC_IOPATH_2) +X(timing_RAM_NOECC_IOPATH_3) +X(timing_RAM_NOECC_IOPATH_4) +X(timing_RAM_NOECC_SETUPHOLD_1) +X(timing_RAM_NOECC_SETUPHOLD_10) +X(timing_RAM_NOECC_SETUPHOLD_2) +X(timing_RAM_NOECC_SETUPHOLD_3) +X(timing_RAM_NOECC_SETUPHOLD_4) +X(timing_RAM_NOECC_SETUPHOLD_5) +X(timing_RAM_NOECC_SETUPHOLD_6) +X(timing_RAM_NOECC_SETUPHOLD_7) +X(timing_RAM_NOECC_SETUPHOLD_8) +X(timing_RAM_NOECC_SETUPHOLD_9) +X(timing_RAM_NOECC_WIDTH) +X(timing_RAM_REG_IOPATH_1) +X(timing_RAM_REG_IOPATH_2) +X(timing_RAM_REG_IOPATH_3) +X(timing_RAM_REG_IOPATH_4) +X(timing_RAM_REG_SETUPHOLD_1) +X(timing_RAM_REG_SETUPHOLD_10) +X(timing_RAM_REG_SETUPHOLD_2) +X(timing_RAM_REG_SETUPHOLD_3) +X(timing_RAM_REG_SETUPHOLD_4) +X(timing_RAM_REG_SETUPHOLD_5) +X(timing_RAM_REG_SETUPHOLD_6) +X(timing_RAM_REG_SETUPHOLD_7) +X(timing_RAM_REG_SETUPHOLD_8) +X(timing_RAM_REG_SETUPHOLD_9) +X(timing_RAM_REG_WIDTH) +X(timing__ADDF2X_CINX_COUTX) +X(timing__ADDF2X_IN1_COUTX) +X(timing__ADDF2X_IN1_OUT1) +X(timing__ADDF2X_IN1_OUT2) +X(timing__ADDF2X_IN1_RAM_O1) +X(timing__ADDF2X_IN1_RAM_O2) +X(timing__ADDF2X_IN2_COUTX) +X(timing__ADDF2X_IN2_OUT1) +X(timing__ADDF2X_IN2_OUT2) +X(timing__ADDF2X_IN2_RAM_O1) +X(timing__ADDF2X_IN2_RAM_O2) +X(timing__ADDF2X_IN3_COUTX) +X(timing__ADDF2X_IN3_OUT1) +X(timing__ADDF2X_IN3_OUT2) +X(timing__ADDF2X_IN3_RAM_O1) +X(timing__ADDF2X_IN3_RAM_O2) +X(timing__ADDF2X_IN4_COUTX) +X(timing__ADDF2X_IN4_OUT1) +X(timing__ADDF2X_IN4_OUT2) +X(timing__ADDF2X_IN4_RAM_O1) +X(timing__ADDF2X_IN4_RAM_O2) +X(timing__ADDF2X_IN5_COUTX) +X(timing__ADDF2X_IN5_OUT1) +X(timing__ADDF2X_IN5_OUT2) +X(timing__ADDF2X_IN5_RAM_O1) +X(timing__ADDF2X_IN5_RAM_O2) +X(timing__ADDF2X_IN6_COUTX) +X(timing__ADDF2X_IN6_OUT1) +X(timing__ADDF2X_IN6_OUT2) +X(timing__ADDF2X_IN6_RAM_O1) +X(timing__ADDF2X_IN6_RAM_O2) +X(timing__ADDF2X_IN7_COUTX) +X(timing__ADDF2X_IN7_OUT1) +X(timing__ADDF2X_IN7_OUT2) +X(timing__ADDF2X_IN7_RAM_O1) +X(timing__ADDF2X_IN7_RAM_O2) +X(timing__ADDF2X_IN8_COUTX) +X(timing__ADDF2X_IN8_OUT1) +X(timing__ADDF2X_IN8_OUT2) +X(timing__ADDF2X_IN8_RAM_O1) +X(timing__ADDF2X_IN8_RAM_O2) +X(timing__ADDF2Y1_CINY1_COUTY) +X(timing__ADDF2Y1_CINY1_OUT1) +X(timing__ADDF2Y1_CINY1_OUT2) +X(timing__ADDF2Y1_IN1_COUTY1) +X(timing__ADDF2Y1_IN1_OUT1) +X(timing__ADDF2Y1_IN1_OUT2) +X(timing__ADDF2Y1_IN1_RAM_O1) +X(timing__ADDF2Y1_IN1_RAM_O2) +X(timing__ADDF2Y1_IN2_COUTY1) +X(timing__ADDF2Y1_IN2_OUT1) +X(timing__ADDF2Y1_IN2_OUT2) +X(timing__ADDF2Y1_IN2_RAM_O1) +X(timing__ADDF2Y1_IN2_RAM_O2) +X(timing__ADDF2Y1_IN3_COUTY1) +X(timing__ADDF2Y1_IN3_OUT1) +X(timing__ADDF2Y1_IN3_OUT2) +X(timing__ADDF2Y1_IN3_RAM_O1) +X(timing__ADDF2Y1_IN3_RAM_O2) +X(timing__ADDF2Y1_IN4_COUTY1) +X(timing__ADDF2Y1_IN4_OUT1) +X(timing__ADDF2Y1_IN4_OUT2) +X(timing__ADDF2Y1_IN4_RAM_O1) +X(timing__ADDF2Y1_IN4_RAM_O2) +X(timing__ADDF2Y1_IN5_COUTY1) +X(timing__ADDF2Y1_IN5_OUT1) +X(timing__ADDF2Y1_IN5_OUT2) +X(timing__ADDF2Y1_IN5_RAM_O1) +X(timing__ADDF2Y1_IN5_RAM_O2) +X(timing__ADDF2Y1_IN6_COUTY1) +X(timing__ADDF2Y1_IN6_OUT1) +X(timing__ADDF2Y1_IN6_OUT2) +X(timing__ADDF2Y1_IN6_RAM_O1) +X(timing__ADDF2Y1_IN6_RAM_O2) +X(timing__ADDF2Y1_IN7_COUTY1) +X(timing__ADDF2Y1_IN7_OUT1) +X(timing__ADDF2Y1_IN7_OUT2) +X(timing__ADDF2Y1_IN7_RAM_O1) +X(timing__ADDF2Y1_IN7_RAM_O2) +X(timing__ADDF2Y1_IN8_COUTY1) +X(timing__ADDF2Y1_IN8_OUT1) +X(timing__ADDF2Y1_IN8_OUT2) +X(timing__ADDF2Y1_IN8_RAM_O1) +X(timing__ADDF2Y1_IN8_RAM_O2) +X(timing__ARBLUT_IN1_OUT1) +X(timing__ARBLUT_IN1_OUT2) +X(timing__ARBLUT_IN1_RAM_O1) +X(timing__ARBLUT_IN1_RAM_O2) +X(timing__ARBLUT_IN2_OUT1) +X(timing__ARBLUT_IN2_OUT2) +X(timing__ARBLUT_IN2_RAM_O1) +X(timing__ARBLUT_IN2_RAM_O2) +X(timing__ARBLUT_IN3_OUT1) +X(timing__ARBLUT_IN3_OUT2) +X(timing__ARBLUT_IN3_RAM_O1) +X(timing__ARBLUT_IN3_RAM_O2) +X(timing__ARBLUT_IN4_OUT1) +X(timing__ARBLUT_IN4_OUT2) +X(timing__ARBLUT_IN4_RAM_O1) +X(timing__ARBLUT_IN4_RAM_O2) +X(timing__ARBLUT_IN5_OUT1) +X(timing__ARBLUT_IN5_RAM_O1) +X(timing__ARBLUT_IN5_RAM_O2) +X(timing__ARBLUT_IN6_OUT1) +X(timing__ARBLUT_IN6_RAM_O1) +X(timing__ARBLUT_IN6_RAM_O2) +X(timing__ARBLUT_IN7_OUT1) +X(timing__ARBLUT_IN7_RAM_O1) +X(timing__ARBLUT_IN7_RAM_O2) +X(timing__ARBLUT_IN8_OUT1) +X(timing__ARBLUT_IN8_RAM_O1) +X(timing__ARBLUT_IN8_RAM_O2) +X(timing__ARBLUT_RAM_I1_COUTX) +X(timing__ARBLUT_RAM_I1_OUT1) +X(timing__ARBLUT_RAM_I1_POUTX) +X(timing__ARBLUT_RAM_I2_OUT2) +X(timing__ARBLUT_RAM_I2_POUTX) +X(timing__ARBLUT_RAM_O____RAM) +X(timing__MULT_CINX_COUTX) +X(timing__MULT_CINX_COUTY1) +X(timing__MULT_CINX_COUTY2) +X(timing__MULT_CINY1_COUTX) +X(timing__MULT_CINY1_COUTY1) +X(timing__MULT_CINY1_COUTY2) +X(timing__MULT_CINY1_POUTX) +X(timing__MULT_CINY2_COUTX) +X(timing__MULT_CINY2_COUTY2) +X(timing__MULT_CINY2_POUTX) +X(timing__MULT_IN1_COUTX) +X(timing__MULT_IN1_COUTY1) +X(timing__MULT_IN1_COUTY2) +X(timing__MULT_IN1_RAM_O1) +X(timing__MULT_IN1_RAM_O2) +X(timing__MULT_IN2_RAM_O1) +X(timing__MULT_IN2_RAM_O2) +X(timing__MULT_IN3_RAM_O1) +X(timing__MULT_IN3_RAM_O2) +X(timing__MULT_IN4_RAM_O1) +X(timing__MULT_IN4_RAM_O2) +X(timing__MULT_IN5_COUTX) +X(timing__MULT_IN5_COUTY1) +X(timing__MULT_IN5_COUTY2) +X(timing__MULT_IN5_POUTX) +X(timing__MULT_IN5_RAM_O1) +X(timing__MULT_IN5_RAM_O2) +X(timing__MULT_IN6_RAM_O1) +X(timing__MULT_IN6_RAM_O2) +X(timing__MULT_IN7_RAM_O1) +X(timing__MULT_IN7_RAM_O2) +X(timing__MULT_IN8_COUTX) +X(timing__MULT_IN8_COUTY2) +X(timing__MULT_IN8_POUTX) +X(timing__MULT_IN8_RAM_O1) +X(timing__MULT_IN8_RAM_O2) +X(timing__MULT_PINX_COUTX) +X(timing__MULT_PINX_COUTY1) +X(timing__MULT_PINX_COUTY2) +X(timing__MULT_PINX_POUTX) +X(timing__MULT_PINY1_COUTX) +X(timing__MULT_PINY1_COUTY1) +X(timing__MULT_PINY1_COUTY2) +X(timing__MULT_PINY1_POUTX) +X(timing__MULT_PINY1_POUTY1) +X(timing__MULT_PINY2_COUTX) +X(timing__MULT_PINY2_COUTY2) +X(timing__MULT_PINY2_POUTX) +X(timing__MULT_PINY2_POUTY2) +X(timing__MX4A_IN1_OUT1) +X(timing__MX4A_IN1_RAM_O1) +X(timing__MX4A_IN1_RAM_O2) +X(timing__MX4A_IN2_OUT1) +X(timing__MX4A_IN2_RAM_O1) +X(timing__MX4A_IN2_RAM_O2) +X(timing__MX4A_IN3_OUT1) +X(timing__MX4A_IN3_RAM_O1) +X(timing__MX4A_IN3_RAM_O2) +X(timing__MX4A_IN4_OUT1) +X(timing__MX4A_IN4_RAM_O1) +X(timing__MX4A_IN4_RAM_O2) +X(timing__MX4A_IN5_OUT1) +X(timing__MX4A_IN5_RAM_O1) +X(timing__MX4A_IN5_RAM_O2) +X(timing__MX4A_IN6_OUT1) +X(timing__MX4A_IN6_RAM_O1) +X(timing__MX4A_IN6_RAM_O2) +X(timing__MX4A_IN7_OUT1) +X(timing__MX4A_IN7_RAM_O1) +X(timing__MX4A_IN7_RAM_O2) +X(timing__MX4A_IN8_OUT1) +X(timing__MX4A_IN8_RAM_O1) +X(timing__MX4A_IN8_RAM_O2) +X(timing__MX4B_IN1_OUT1) +X(timing__MX4B_IN1_OUT2) +X(timing__MX4B_IN1_RAM_O1) +X(timing__MX4B_IN1_RAM_O2) +X(timing__MX4B_IN2_OUT1) +X(timing__MX4B_IN2_OUT2) +X(timing__MX4B_IN2_RAM_O1) +X(timing__MX4B_IN2_RAM_O2) +X(timing__MX4B_IN3_OUT1) +X(timing__MX4B_IN3_OUT2) +X(timing__MX4B_IN3_RAM_O1) +X(timing__MX4B_IN3_RAM_O2) +X(timing__MX4B_IN4_OUT1) +X(timing__MX4B_IN4_OUT2) +X(timing__MX4B_IN4_RAM_O1) +X(timing__MX4B_IN4_RAM_O2) +X(timing__MX4B_IN5_OUT1) +X(timing__MX4B_IN5_OUT2) +X(timing__MX4B_IN5_RAM_O1) +X(timing__MX4B_IN5_RAM_O2) +X(timing__MX4B_IN6_OUT1) +X(timing__MX4B_IN6_OUT2) +X(timing__MX4B_IN6_RAM_O1) +X(timing__MX4B_IN6_RAM_O2) +X(timing__MX4B_IN7_OUT1) +X(timing__MX4B_IN7_OUT2) +X(timing__MX4B_IN7_RAM_O1) +X(timing__MX4B_IN7_RAM_O2) +X(timing__MX4B_IN8_OUT1) +X(timing__MX4B_IN8_OUT2) +X(timing__MX4B_IN8_RAM_O1) +X(timing__MX4B_IN8_RAM_O2) +X(timing__MX8_CLK_OUT1) +X(timing__MX8_CLK_OUT2) +X(timing__MX8_EN_OUT1) +X(timing__MX8_EN_OUT2) +X(timing__MX8_IN1_OUT1) +X(timing__MX8_IN1_OUT2) +X(timing__MX8_IN1_RAM_O1) +X(timing__MX8_IN1_RAM_O2) +X(timing__MX8_IN2_OUT1) +X(timing__MX8_IN2_OUT2) +X(timing__MX8_IN2_RAM_O1) +X(timing__MX8_IN2_RAM_O2) +X(timing__MX8_IN3_OUT1) +X(timing__MX8_IN3_OUT2) +X(timing__MX8_IN3_RAM_O1) +X(timing__MX8_IN3_RAM_O2) +X(timing__MX8_IN4_OUT1) +X(timing__MX8_IN4_OUT2) +X(timing__MX8_IN4_RAM_O1) +X(timing__MX8_IN4_RAM_O2) +X(timing__MX8_IN5_OUT1) +X(timing__MX8_IN5_OUT2) +X(timing__MX8_IN5_RAM_O1) +X(timing__MX8_IN5_RAM_O2) +X(timing__MX8_IN6_OUT1) +X(timing__MX8_IN6_OUT2) +X(timing__MX8_IN6_RAM_O1) +X(timing__MX8_IN6_RAM_O2) +X(timing__MX8_IN7_OUT1) +X(timing__MX8_IN7_OUT2) +X(timing__MX8_IN7_RAM_O1) +X(timing__MX8_IN7_RAM_O2) +X(timing__MX8_IN8_OUT1) +X(timing__MX8_IN8_OUT2) +X(timing__MX8_IN8_RAM_O1) +X(timing__MX8_IN8_RAM_O2) +X(timing__MX8_SR_OUT1) +X(timing__MX8_SR_OUT2) +X(timing__ROUTING_CINX_COUTX) +X(timing__ROUTING_CINX_COUTY1) +X(timing__ROUTING_CINX_COUTY2) +X(timing__ROUTING_CINX_POUTX) +X(timing__ROUTING_CINX_POUTY1) +X(timing__ROUTING_CINX_POUTY2) +X(timing__ROUTING_CINY1_COUTX) +X(timing__ROUTING_CINY1_COUTY) +X(timing__ROUTING_CINY1_POUTX) +X(timing__ROUTING_CINY1_POUTY) +X(timing__ROUTING_CINY2_COUTX) +X(timing__ROUTING_CINY2_COUTY) +X(timing__ROUTING_IN1_RAM_O1) +X(timing__ROUTING_IN1_RAM_O2) +X(timing__ROUTING_IN2_RAM_O1) +X(timing__ROUTING_IN2_RAM_O2) +X(timing__ROUTING_IN3_RAM_O1) +X(timing__ROUTING_IN3_RAM_O2) +X(timing__ROUTING_IN4_RAM_O1) +X(timing__ROUTING_IN4_RAM_O2) +X(timing__ROUTING_IN5_RAM_O1) +X(timing__ROUTING_IN5_RAM_O2) +X(timing__ROUTING_IN6_RAM_O1) +X(timing__ROUTING_IN6_RAM_O2) +X(timing__ROUTING_IN7_RAM_O1) +X(timing__ROUTING_IN7_RAM_O2) +X(timing__ROUTING_IN8_RAM_O1) +X(timing__ROUTING_IN8_RAM_O2) +X(timing__ROUTING_PINX_COUTX) +X(timing__ROUTING_PINX_COUTY1) +X(timing__ROUTING_PINX_COUTY2) +X(timing__ROUTING_PINX_POUTX) +X(timing__ROUTING_PINX_POUTY1) +X(timing__ROUTING_PINX_POUTY2) +X(timing__ROUTING_PINY1_COUTX) +X(timing__ROUTING_PINY1_COUTY) +X(timing__ROUTING_PINY1_POUTX) +X(timing__ROUTING_PINY1_POUTY) +X(timing__ROUTING_PINY2_POUTY) +X(timing__SEQ_CINX_FF1_D) +X(timing__SEQ_CINX_FF2_D) +X(timing__SEQ_CINX_LH1_D) +X(timing__SEQ_CINX_LH2_D) +X(timing__SEQ_CINY1_FF1_D) +X(timing__SEQ_CINY1_FF2_D) +X(timing__SEQ_CINY1_LH1_D) +X(timing__SEQ_CINY1_LH2_D) +X(timing__SEQ_CINY2_FF1_Q) +X(timing__SEQ_CINY2_FF2_Q) +X(timing__SEQ_CINY2_LH1_Q) +X(timing__SEQ_CINY2_LH2_Q) +X(timing__SEQ_CLK_FF1_Q) +X(timing__SEQ_CLK_FF2_Q) +X(timing__SEQ_CLK_LH1_Q) +X(timing__SEQ_CLK_LH2_Q) +X(timing__SEQ_EN_FF1_EN) +X(timing__SEQ_EN_FF2_EN) +X(timing__SEQ_EN_LH1_EN) +X(timing__SEQ_EN_LH2_EN) +X(timing__SEQ_IN1_FF1_D) +X(timing__SEQ_IN1_FF2_D) +X(timing__SEQ_IN1_LH1_D) +X(timing__SEQ_IN1_LH2_D) +X(timing__SEQ_IN2_FF1_D) +X(timing__SEQ_IN2_FF2_D) +X(timing__SEQ_IN2_LH1_D) +X(timing__SEQ_IN2_LH2_D) +X(timing__SEQ_IN3_FF1_D) +X(timing__SEQ_IN3_FF2_D) +X(timing__SEQ_IN3_LH1_D) +X(timing__SEQ_IN3_LH2_D) +X(timing__SEQ_IN4_FF1_D) +X(timing__SEQ_IN4_FF2_D) +X(timing__SEQ_IN4_LH1_D) +X(timing__SEQ_IN4_LH2_D) +X(timing__SEQ_IN5_FF1_D) +X(timing__SEQ_IN5_FF2_D) +X(timing__SEQ_IN5_LH1_D) +X(timing__SEQ_IN5_LH2_D) +X(timing__SEQ_IN6_FF1_D) +X(timing__SEQ_IN6_FF2_D) +X(timing__SEQ_IN6_LH1_D) +X(timing__SEQ_IN6_LH2_D) +X(timing__SEQ_IN7_FF1_D) +X(timing__SEQ_IN7_FF2_D) +X(timing__SEQ_IN7_LH1_D) +X(timing__SEQ_IN7_LH2_D) +X(timing__SEQ_IN8_FF1_D) +X(timing__SEQ_IN8_FF2_D) +X(timing__SEQ_IN8_LH1_D) +X(timing__SEQ_IN8_LH2_D) +X(timing__SEQ_PINX_FF1_D) +X(timing__SEQ_PINX_FF2_D) +X(timing__SEQ_PINX_LH1_D) +X(timing__SEQ_PINX_LH2_D) +X(timing__SEQ_PINY1_FF1_D) +X(timing__SEQ_PINY1_FF2_D) +X(timing__SEQ_PINY1_LH1_D) +X(timing__SEQ_PINY1_LH2_D) +X(timing__SEQ_PINY2_FF1_EN) +X(timing__SEQ_PINY2_FF2_EN) +X(timing__SEQ_PINY2_LH1_EN) +X(timing__SEQ_PINY2_LH2_EN) +X(timing__SEQ_RAM_I1_FF1_D) +X(timing__SEQ_RAM_I1_FF2_D) +X(timing__SEQ_RAM_I1_LH1_D) +X(timing__SEQ_RAM_I1_LH2_D) +X(timing__SEQ_RAM_I2_FF1_D) +X(timing__SEQ_RAM_I2_FF2_D) +X(timing__SEQ_RAM_I2_LH1_D) +X(timing__SEQ_RAM_I2_LH2_D) +X(timing__SEQ_SR_FF1_SR) +X(timing__SEQ_SR_FF2_SR) +X(timing__SEQ_SR_LH1_SR) +X(timing__SEQ_SR_LH2_SR) +X(timing_clkin_CLK0_CLK_REF0) +X(timing_clkin_CLK0_CLK_REF1) +X(timing_clkin_CLK0_CLK_REF2) +X(timing_clkin_CLK0_CLK_REF3) +X(timing_clkin_CLK1_CLK_REF0) +X(timing_clkin_CLK1_CLK_REF1) +X(timing_clkin_CLK1_CLK_REF2) +X(timing_clkin_CLK1_CLK_REF3) +X(timing_clkin_CLK2_CLK_REF0) +X(timing_clkin_CLK2_CLK_REF1) +X(timing_clkin_CLK2_CLK_REF2) +X(timing_clkin_CLK2_CLK_REF3) +X(timing_clkin_CLK3_CLK_REF0) +X(timing_clkin_CLK3_CLK_REF1) +X(timing_clkin_CLK3_CLK_REF2) +X(timing_clkin_CLK3_CLK_REF3) +X(timing_clkin_JTAG_CLK_CLK_REF0) +X(timing_clkin_JTAG_CLK_CLK_REF1) +X(timing_clkin_JTAG_CLK_CLK_REF2) +X(timing_clkin_JTAG_CLK_CLK_REF3) +X(timing_clkin_SER_CLK_CLK_REF0) +X(timing_clkin_SER_CLK_CLK_REF1) +X(timing_clkin_SER_CLK_CLK_REF2) +X(timing_clkin_SER_CLK_CLK_REF3) +X(timing_clkin_SPI_CLK_CLK_REF0) +X(timing_clkin_SPI_CLK_CLK_REF1) +X(timing_clkin_SPI_CLK_CLK_REF2) +X(timing_clkin_SPI_CLK_CLK_REF3) +X(timing_comb12_COUTX) +X(timing_comb12_COUTY1) +X(timing_comb12_COUTY2) +X(timing_comb12_POUTX) +X(timing_comb12_POUTY1) +X(timing_comb12_POUTY2) +X(timing_comb12_RAM_O1) +X(timing_comb12_RAM_O2) +X(timing_comb12_compout_COUTX) +X(timing_comb12_compout_COUTY) +X(timing_comb12_compout_POUTX) +X(timing_comb12_compout_POUTY) +X(timing_comb1_D1) +X(timing_comb1_L1) +X(timing_comb1_OUT1) +X(timing_comb1_compout) +X(timing_comb2_D2) +X(timing_comb2_L2) +X(timing_comb2_OUT2) +X(timing_comb2_compout) +X(timing_cpout_OUT1) +X(timing_cpout_OUT2) +X(timing_del_CPE_CP_Q) +X(timing_del_CPE_D_Q) +X(timing_del_CPE_R_Q) +X(timing_del_CPE_S_Q) +X(timing_del_CP_carry_path) +X(timing_del_CP_clkin) +X(timing_del_CP_enin) +X(timing_del_CP_prop_path) +X(timing_del_GLBOUT_IO_SEL) +X(timing_del_GLBOUT_sb_big) +X(timing_del_Hold_D_L) +X(timing_del_Hold_RAM) +X(timing_del_Hold_RN_SN) +X(timing_del_Hold_SN_RN) +X(timing_del_IBF) +X(timing_del_IO_SEL_Q_in) +X(timing_del_IO_SEL_Q_out) +X(timing_del_LVDS_IBF) +X(timing_del_LVDS_OBF) +X(timing_del_LVDS_TOBF_ctrl) +X(timing_del_OBF) +X(timing_del_RAMO_xOBF) +X(timing_del_RAM_CLK_DO) +X(timing_del_Setup_D_L) +X(timing_del_Setup_RAM) +X(timing_del_Setup_RN_SN) +X(timing_del_Setup_SN_RN) +X(timing_del_TOBF_ctrl) +X(timing_del_bot_SB_couty2) +X(timing_del_bot_SB_pouty2) +X(timing_del_bot_couty2) +X(timing_del_bot_glb_couty2) +X(timing_del_bot_glb_pouty2) +X(timing_del_bot_pouty2) +X(timing_del_ddel_LVDS_r_OBFummy) +X(timing_del_dummy) +X(timing_del_left_SB_couty2) +X(timing_del_left_SB_pouty2) +X(timing_del_left_couty2) +X(timing_del_left_glb_couty2) +X(timing_del_left_glb_pouty2) +X(timing_del_left_pouty2) +X(timing_del_min_route_SB) +X(timing_del_r_OBF) +X(timing_del_sb_drv) +X(timing_del_special_RAM_I) +X(timing_del_violation_common) +X(timing_glbout_CLK0_0_CLK_FB0) +X(timing_glbout_CLK0_0_CLK_FB1) +X(timing_glbout_CLK0_0_CLK_FB2) +X(timing_glbout_CLK0_0_CLK_FB3) +X(timing_glbout_CLK0_0_GLB0) +X(timing_glbout_CLK0_1_CLK_FB0) +X(timing_glbout_CLK0_1_CLK_FB1) +X(timing_glbout_CLK0_1_CLK_FB2) +X(timing_glbout_CLK0_1_CLK_FB3) +X(timing_glbout_CLK0_1_GLB0) +X(timing_glbout_CLK0_1_GLB1) +X(timing_glbout_CLK0_2_CLK_FB0) +X(timing_glbout_CLK0_2_CLK_FB1) +X(timing_glbout_CLK0_2_CLK_FB2) +X(timing_glbout_CLK0_2_CLK_FB3) +X(timing_glbout_CLK0_2_GLB0) +X(timing_glbout_CLK0_2_GLB2) +X(timing_glbout_CLK0_3_CLK_FB0) +X(timing_glbout_CLK0_3_CLK_FB1) +X(timing_glbout_CLK0_3_CLK_FB2) +X(timing_glbout_CLK0_3_CLK_FB3) +X(timing_glbout_CLK0_3_GLB0) +X(timing_glbout_CLK0_3_GLB3) +X(timing_glbout_CLK180_0_CLK_FB0) +X(timing_glbout_CLK180_0_CLK_FB1) +X(timing_glbout_CLK180_0_CLK_FB2) +X(timing_glbout_CLK180_0_CLK_FB3) +X(timing_glbout_CLK180_0_GLB0) +X(timing_glbout_CLK180_0_GLB2) +X(timing_glbout_CLK180_1_CLK_FB0) +X(timing_glbout_CLK180_1_CLK_FB1) +X(timing_glbout_CLK180_1_CLK_FB2) +X(timing_glbout_CLK180_1_CLK_FB3) +X(timing_glbout_CLK180_1_GLB1) +X(timing_glbout_CLK180_1_GLB2) +X(timing_glbout_CLK180_2_CLK_FB0) +X(timing_glbout_CLK180_2_CLK_FB1) +X(timing_glbout_CLK180_2_CLK_FB2) +X(timing_glbout_CLK180_2_CLK_FB3) +X(timing_glbout_CLK180_2_GLB2) +X(timing_glbout_CLK180_3_CLK_FB0) +X(timing_glbout_CLK180_3_CLK_FB1) +X(timing_glbout_CLK180_3_CLK_FB2) +X(timing_glbout_CLK180_3_CLK_FB3) +X(timing_glbout_CLK180_3_GLB2) +X(timing_glbout_CLK180_3_GLB3) +X(timing_glbout_CLK270_0_CLK_FB0) +X(timing_glbout_CLK270_0_CLK_FB1) +X(timing_glbout_CLK270_0_CLK_FB2) +X(timing_glbout_CLK270_0_CLK_FB3) +X(timing_glbout_CLK270_0_GLB0) +X(timing_glbout_CLK270_0_GLB3) +X(timing_glbout_CLK270_1_CLK_FB0) +X(timing_glbout_CLK270_1_CLK_FB1) +X(timing_glbout_CLK270_1_CLK_FB2) +X(timing_glbout_CLK270_1_CLK_FB3) +X(timing_glbout_CLK270_1_GLB1) +X(timing_glbout_CLK270_1_GLB3) +X(timing_glbout_CLK270_2_CLK_FB0) +X(timing_glbout_CLK270_2_CLK_FB1) +X(timing_glbout_CLK270_2_CLK_FB2) +X(timing_glbout_CLK270_2_CLK_FB3) +X(timing_glbout_CLK270_2_GLB2) +X(timing_glbout_CLK270_2_GLB3) +X(timing_glbout_CLK270_3_CLK_FB0) +X(timing_glbout_CLK270_3_CLK_FB1) +X(timing_glbout_CLK270_3_CLK_FB2) +X(timing_glbout_CLK270_3_CLK_FB3) +X(timing_glbout_CLK270_3_GLB3) +X(timing_glbout_CLK90_0_CLK_FB0) +X(timing_glbout_CLK90_0_CLK_FB1) +X(timing_glbout_CLK90_0_CLK_FB2) +X(timing_glbout_CLK90_0_CLK_FB3) +X(timing_glbout_CLK90_0_GLB0) +X(timing_glbout_CLK90_0_GLB1) +X(timing_glbout_CLK90_1_CLK_FB0) +X(timing_glbout_CLK90_1_CLK_FB1) +X(timing_glbout_CLK90_1_CLK_FB2) +X(timing_glbout_CLK90_1_CLK_FB3) +X(timing_glbout_CLK90_1_GLB1) +X(timing_glbout_CLK90_2_CLK_FB0) +X(timing_glbout_CLK90_2_CLK_FB1) +X(timing_glbout_CLK90_2_CLK_FB2) +X(timing_glbout_CLK90_2_CLK_FB3) +X(timing_glbout_CLK90_2_GLB1) +X(timing_glbout_CLK90_2_GLB2) +X(timing_glbout_CLK90_3_CLK_FB0) +X(timing_glbout_CLK90_3_CLK_FB1) +X(timing_glbout_CLK90_3_CLK_FB2) +X(timing_glbout_CLK90_3_CLK_FB3) +X(timing_glbout_CLK90_3_GLB1) +X(timing_glbout_CLK90_3_GLB3) +X(timing_glbout_CLK_REF_OUT0_CLK_FB0) +X(timing_glbout_CLK_REF_OUT0_CLK_FB1) +X(timing_glbout_CLK_REF_OUT0_CLK_FB2) +X(timing_glbout_CLK_REF_OUT0_CLK_FB3) +X(timing_glbout_CLK_REF_OUT0_GLB0) +X(timing_glbout_CLK_REF_OUT1_CLK_FB0) +X(timing_glbout_CLK_REF_OUT1_CLK_FB1) +X(timing_glbout_CLK_REF_OUT1_CLK_FB2) +X(timing_glbout_CLK_REF_OUT1_CLK_FB3) +X(timing_glbout_CLK_REF_OUT1_GLB1) +X(timing_glbout_CLK_REF_OUT2_CLK_FB0) +X(timing_glbout_CLK_REF_OUT2_CLK_FB1) +X(timing_glbout_CLK_REF_OUT2_CLK_FB2) +X(timing_glbout_CLK_REF_OUT2_CLK_FB3) +X(timing_glbout_CLK_REF_OUT2_GLB2) +X(timing_glbout_CLK_REF_OUT3_CLK_FB0) +X(timing_glbout_CLK_REF_OUT3_CLK_FB1) +X(timing_glbout_CLK_REF_OUT3_CLK_FB2) +X(timing_glbout_CLK_REF_OUT3_CLK_FB3) +X(timing_glbout_CLK_REF_OUT3_GLB3) +X(timing_glbout_FEEDBACK_delay) +X(timing_glbout_USR_FB0_CLK_FB0) +X(timing_glbout_USR_FB1_CLK_FB1) +X(timing_glbout_USR_FB2_CLK_FB2) +X(timing_glbout_USR_FB3_CLK_FB3) +X(timing_glbout_USR_GLB0_CLK_FB0) +X(timing_glbout_USR_GLB0_CLK_FB1) +X(timing_glbout_USR_GLB0_CLK_FB2) +X(timing_glbout_USR_GLB0_CLK_FB3) +X(timing_glbout_USR_GLB0_GLB0) +X(timing_glbout_USR_GLB1_CLK_FB0) +X(timing_glbout_USR_GLB1_CLK_FB1) +X(timing_glbout_USR_GLB1_CLK_FB2) +X(timing_glbout_USR_GLB1_CLK_FB3) +X(timing_glbout_USR_GLB1_GLB1) +X(timing_glbout_USR_GLB2_CLK_FB0) +X(timing_glbout_USR_GLB2_CLK_FB1) +X(timing_glbout_USR_GLB2_CLK_FB2) +X(timing_glbout_USR_GLB2_CLK_FB3) +X(timing_glbout_USR_GLB2_GLB2) +X(timing_glbout_USR_GLB3_CLK_FB0) +X(timing_glbout_USR_GLB3_CLK_FB1) +X(timing_glbout_USR_GLB3_CLK_FB2) +X(timing_glbout_USR_GLB3_CLK_FB3) +X(timing_glbout_USR_GLB3_GLB3) +X(timing_in_delayline_per_stage) +X(timing_io_sel_CLOCK0_GPIO_OUT) +X(timing_io_sel_CLOCK0_IN1) +X(timing_io_sel_CLOCK0_IN2) +X(timing_io_sel_CLOCK1_GPIO_OUT) +X(timing_io_sel_CLOCK1_IN1) +X(timing_io_sel_CLOCK1_IN2) +X(timing_io_sel_CLOCK2_GPIO_OUT) +X(timing_io_sel_CLOCK2_IN1) +X(timing_io_sel_CLOCK2_IN2) +X(timing_io_sel_CLOCK3_GPIO_OUT) +X(timing_io_sel_CLOCK3_IN1) +X(timing_io_sel_CLOCK3_IN2) +X(timing_io_sel_GPIO_IN_IN1) +X(timing_io_sel_GPIO_IN_IN2) +X(timing_io_sel_OUT1_GPIO_OUT) +X(timing_io_sel_OUT1_IN1) +X(timing_io_sel_OUT1_IN2) +X(timing_io_sel_OUT2_GPIO_EN) +X(timing_io_sel_OUT2_GPIO_OUT) +X(timing_io_sel_OUT3_GPIO_EN) +X(timing_io_sel_OUT3_GPIO_OUT) +X(timing_io_sel_OUT4_GPIO_EN) +X(timing_io_sel_OUT4_GPIO_OUT) +X(timing_io_sel_OUT4_IN1) +X(timing_io_sel_OUT4_IN2) +X(timing_mout_D2) +X(timing_mout_L2) +X(timing_mout_OUT1) +X(timing_mout_OUT2) +X(timing_out_delayline_per_stage) +X(timing_pll_clk_ref_i_clk_core0_o) +X(timing_pll_clk_ref_i_clk_core180_o) +X(timing_pll_clk_ref_i_clk_core270_o) +X(timing_pll_clk_ref_i_clk_core90_o) +X(timing_pll_clock_core0_i_clk_core0_o) +X(timing_pll_clock_core0_i_clk_core180_o) +X(timing_pll_clock_core0_i_clk_core270_o) +X(timing_pll_clock_core0_i_clk_core90_o) +X(timing_pll_locked_steady_reset_i_pll_locked_steady_o) diff --git a/himbaechel/uarch/gatemate/delay.cc b/himbaechel/uarch/gatemate/delay.cc new file mode 100644 index 00000000..bc98167d --- /dev/null +++ b/himbaechel/uarch/gatemate/delay.cc @@ -0,0 +1,356 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2024 The Project Peppercorn Authors. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include +#include + +#include "gatemate.h" + +#define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc" +#include "himbaechel_constids.h" + +NEXTPNR_NAMESPACE_BEGIN + +delay_t GateMateImpl::estimateDelay(WireId src, WireId dst) const +{ + int sx, sy, dx, dy; + tile_xy(ctx->chip_info, src.tile, sx, sy); + tile_xy(ctx->chip_info, dst.tile, dx, dy); + + return 100 + 100 * (std::abs(dx - sx) + std::abs(dy - sy)); +} + +bool GateMateImpl::get_delay_from_tmg_db(IdString id, DelayQuad &delay) const +{ + auto fnd = timing.find(id); + if (fnd != timing.end()) { + delay = DelayQuad(fnd->second->delay.fast_min, fnd->second->delay.fast_max, fnd->second->delay.slow_min, + fnd->second->delay.slow_max); + return true; + } + return false; +} + +void GateMateImpl::get_setuphold_from_tmg_db(IdString id_setup, IdString id_hold, DelayPair &setup, + DelayPair &hold) const +{ + auto fnd = timing.find(id_setup); + if (fnd != timing.end()) { + setup.min_delay = fnd->second->delay.fast_min; + setup.max_delay = fnd->second->delay.fast_max; + } + fnd = timing.find(id_hold); + if (fnd != timing.end()) { + hold.min_delay = fnd->second->delay.fast_min; + hold.max_delay = fnd->second->delay.fast_max; + } +} + +void GateMateImpl::get_setuphold_from_tmg_db(IdString id_setuphold, DelayPair &setup, DelayPair &hold) const +{ + auto fnd = timing.find(id_setuphold); + if (fnd != timing.end()) { + setup.min_delay = fnd->second->delay.fast_min; + setup.max_delay = fnd->second->delay.fast_max; + hold.min_delay = fnd->second->delay.slow_min; + hold.max_delay = fnd->second->delay.slow_max; + } +} + +bool GateMateImpl::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const +{ + delay = DelayQuad{0}; + static dict map_upper = { + {id_OUT, id_OUT2}, + {id_RAM_O, id_RAM_O2}, + {id_RAM_I, id_RAM_I2}, + {id_CPOUT, id_CPOUT2}, + }; + static dict map_lower = { + {id_OUT, id_OUT1}, {id_RAM_O, id_RAM_O1}, {id_RAM_I, id_RAM_I1}, {id_CPOUT, id_CPOUT1}, + {id_IN1, id_IN5}, {id_IN2, id_IN6}, {id_IN3, id_IN7}, {id_IN4, id_IN8}, + }; + + int z = (cell->bel != BelId()) ? (ctx->getBelLocation(cell->bel).z % 2) : 0; + if (cell->type.in(id_CPE_L2T4, id_CPE_LT_L, id_CPE_LT_U)) { + IdString fp = fromPort, tp = toPort; + if (z == 0) { + if (map_upper.count(fp)) + fp = map_upper[fp]; + if (map_upper.count(tp)) + tp = map_upper[tp]; + } else { + if (map_lower.count(fp)) + fp = map_lower[fp]; + if (map_lower.count(tp)) + tp = map_lower[tp]; + } + return get_delay_from_tmg_db(ctx->idf("timing__ARBLUT_%s_%s", fp.c_str(ctx), tp.c_str(ctx)), delay); + } else if (cell->type.in(id_CPE_ADDF, id_CPE_ADDF2)) { + return get_delay_from_tmg_db(ctx->idf("timing__ADDF2Y1_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); + } else if (cell->type.in(id_CPE_MX4)) { + return get_delay_from_tmg_db(ctx->idf("timing__MX4A_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); + } else if (cell->type.in(id_CPE_MULT)) { + return get_delay_from_tmg_db(ctx->idf("timing__MULT_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); + } else if (cell->type.in(id_CPE_FF, id_CPE_LATCH, id_CPE_FF_L, id_CPE_FF_U)) { + return false; + } else if (cell->type.in(id_CPE_COMP)) { + return get_delay_from_tmg_db(fromPort == id_COMB1 ? id_timing_comb1_compout : id_timing_comb2_compout, delay); + } else if (cell->type.in(id_CPE_RAMI, id_CPE_RAMO, id_CPE_RAMIO)) { + if (fromPort == id_I && toPort == id_RAM_O) + return get_delay_from_tmg_db(z ? id_timing_comb12_RAM_O1 : id_timing_comb12_RAM_O2, delay); + if (fromPort == id_RAM_I && toPort == id_OUT) + return true; + return false; + } else if (cell->type.in(id_CPE_IBUF, id_CPE_OBUF, id_CPE_TOBUF, id_CPE_IOBUF)) { + if (fromPort == id_A && toPort == id_O) + return get_delay_from_tmg_db(id_timing_del_OBF, delay); + if (fromPort == id_T && toPort == id_O) + return get_delay_from_tmg_db(id_timing_del_TOBF_ctrl, delay); + if (fromPort == id_I && toPort == id_Y) + return get_delay_from_tmg_db(id_timing_del_IBF, delay); + return true; + } else if (cell->type.in(id_CPE_LVDS_IBUF, id_CPE_LVDS_OBUF, id_CPE_LVDS_TOBUF, id_CPE_LVDS_IOBUF)) { + if (fromPort == id_A && toPort.in(id_O_P, id_O_N)) + return get_delay_from_tmg_db(id_timing_del_LVDS_OBF, delay); + if (fromPort == id_T && toPort.in(id_O_P, id_O_N)) + return get_delay_from_tmg_db(id_timing_del_LVDS_TOBF_ctrl, delay); + if (fromPort.in(id_I_P, id_I_N) && toPort == id_Y) + return get_delay_from_tmg_db(id_timing_del_LVDS_IBF, delay); + return true; + } else if (cell->type.in(id_IOSEL)) { + bool output = bool_or_default(cell->params, id_OUT_SIGNAL); + bool enable = bool_or_default(cell->params, id_OE_ENABLE); + IdString o_s = bool_or_default(cell->params, id_OUT23_14_SEL) + ? (bool_or_default(cell->params, id_OUT2_3) ? id_OUT3 : id_OUT2) + : (bool_or_default(cell->params, id_OUT1_4) ? id_OUT4 : id_OUT1); + int oe = int_or_default(cell->params, id_OE_SIGNAL); + IdString oe_s = (oe & 2) ? ((oe & 1) ? id_OUT4 : id_OUT3) : ((oe & 1) ? id_OUT2 : id_OUT1); + if (output && fromPort != o_s) + return false; + if (enable && fromPort != oe_s) + return false; + return get_delay_from_tmg_db(ctx->idf("timing_io_sel_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); + } else if (cell->type.in(id_CLKIN)) { + return get_delay_from_tmg_db(ctx->idf("timing_clkin_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); + } else if (cell->type.in(id_GLBOUT)) { + return get_delay_from_tmg_db(ctx->idf("timing_glbout_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); + } else if (cell->type.in(id_RAM)) { + return false; + } + return false; +} + +TimingPortClass GateMateImpl::getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const +{ + auto disconnected = [cell](IdString p) { return !cell->ports.count(p) || cell->ports.at(p).net == nullptr; }; + clockInfoCount = 0; + if (cell->type.in(id_CPE_L2T4, id_CPE_LT_L, id_CPE_LT_U)) { + if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_COMBIN, id_CINY1, id_CINY2, id_CINX, id_PINX)) + return TMG_COMB_INPUT; + if (port == id_OUT && disconnected(id_IN1) && disconnected(id_IN2) && disconnected(id_IN3) && + disconnected(id_IN4)) + return TMG_IGNORE; // LUT with no inputs is a constant + if (port.in(id_OUT)) + return TMG_COMB_OUTPUT; + return TMG_IGNORE; + } else if (cell->type.in(id_CPE_ADDF, id_CPE_ADDF2)) { + if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_IN5, id_IN6, id_IN7, id_IN8, id_CINX, id_CINY1)) + return TMG_COMB_INPUT; + if (port.in(id_OUT1, id_OUT2, id_COUTY1)) + return TMG_COMB_OUTPUT; + return TMG_IGNORE; + } else if (cell->type.in(id_CPE_MX4)) { + if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_IN5, id_IN6, id_IN7, id_IN8)) + return TMG_COMB_INPUT; + if (port.in(id_OUT1)) + return TMG_COMB_OUTPUT; + return TMG_IGNORE; + } else if (cell->type.in(id_CPE_MULT)) { + if (port.in(id_IN1, id_IN5, id_IN8, id_CINX, id_PINX, id_CINY1, id_CINY2, id_PINY1, id_PINY2)) + return TMG_COMB_INPUT; + return TMG_COMB_OUTPUT; + } else if (cell->type.in(id_CPE_CPLINES)) { + if (port.in(id_OUT1, id_OUT2, id_COMPOUT, id_CINX, id_PINX, id_CINY1, id_PINY1, id_CINY2, id_PINY2)) + return TMG_COMB_INPUT; + return TMG_COMB_OUTPUT; + } else if (cell->type.in(id_CPE_FF, id_CPE_FF_L, id_CPE_FF_U, id_CPE_LATCH)) { + if (port == id_CLK) + return TMG_CLOCK_INPUT; + clockInfoCount = 1; + if (port == id_DOUT) + return TMG_REGISTER_OUTPUT; + // DIN, EN and SR + return TMG_REGISTER_INPUT; + } else if (cell->type.in(id_CPE_RAMI, id_CPE_RAMO, id_CPE_RAMIO, id_CPE_RAMIO_U, id_CPE_RAMIO_L)) { + if (port.in(id_I, id_RAM_I)) + return TMG_COMB_INPUT; + if (port.in(id_O, id_RAM_O)) + return TMG_COMB_OUTPUT; + return TMG_IGNORE; + } else if (cell->type.in(id_CPE_COMP)) { + if (port.in(id_COMB1, id_COMB2)) + return TMG_COMB_INPUT; + return TMG_COMB_OUTPUT; + } else if (cell->type.in(id_CPE_IBUF, id_CPE_OBUF, id_CPE_TOBUF, id_CPE_IOBUF)) { + if (port.in(id_O)) + return TMG_ENDPOINT; + if (port.in(id_Y)) + return TMG_STARTPOINT; + return TMG_IGNORE; + } else if (cell->type.in(id_CPE_LVDS_IBUF, id_CPE_LVDS_OBUF, id_CPE_LVDS_TOBUF, id_CPE_LVDS_IOBUF)) { + if (port.in(id_O_P, id_O_N)) + return TMG_ENDPOINT; + if (port.in(id_Y)) + return TMG_STARTPOINT; + return TMG_IGNORE; + } else if (cell->type.in(id_IOSEL)) { + if (port.in(id_IN1, id_IN2, id_GPIO_EN, id_GPIO_OUT)) + return TMG_COMB_OUTPUT; + if (port.in(id_OUT1, id_OUT2, id_OUT3, id_OUT4, id_GPIO_IN)) + return TMG_COMB_INPUT; + return TMG_IGNORE; + } else if (cell->type.in(id_PLL)) { + if (port.in(id_CLK_REF, id_USR_CLK_REF)) + return TMG_CLOCK_INPUT; + if (port.in(id_CLK0, id_CLK90, id_CLK180, id_CLK270)) + return TMG_GEN_CLOCK; + return TMG_IGNORE; + } else if (cell->type.in(id_CLKIN)) { + if (port.in(id_CLK0, id_CLK1, id_CLK2, id_CLK3, id_SER_CLK)) + return TMG_CLOCK_INPUT; + if (port.in(id_CLK_REF0, id_CLK_REF1, id_CLK_REF2, id_CLK_REF3)) + return TMG_GEN_CLOCK; + return TMG_IGNORE; + } else if (cell->type.in(id_GLBOUT)) { + if (port.in(id_CLK0_0, id_CLK90_0, id_CLK180_0, id_CLK270_0, id_CLK_REF_OUT0, id_CLK0_1, id_CLK90_1, + id_CLK180_1, id_CLK270_1, id_CLK_REF_OUT1, id_CLK0_2, id_CLK90_2, id_CLK180_2, id_CLK270_2, + id_CLK_REF_OUT2, id_CLK0_3, id_CLK90_3, id_CLK180_3, id_CLK270_3, id_CLK_REF_OUT3, id_USR_GLB0, + id_USR_GLB1, id_USR_GLB2, id_USR_GLB3)) + return TMG_CLOCK_INPUT; + if (port.in(id_GLB0, id_GLB1, id_GLB2, id_GLB3)) + return TMG_GEN_CLOCK; + return TMG_IGNORE; + } else if (cell->type.in(id_SERDES)) { + return TMG_IGNORE; + } else if (cell->type.in(id_USR_RSTN)) { + return TMG_IGNORE; + } else if (cell->type.in(id_CFG_CTRL)) { + if (port.in(id_CLK)) + return TMG_CLOCK_INPUT; + return TMG_IGNORE; + } else if (cell->type == id_RAM) { + std::string name = port.str(ctx); + if (boost::starts_with(name, "CLKA[") || boost::starts_with(name, "CLKB[") || boost::starts_with(name, "CLOCK")) + return TMG_CLOCK_INPUT; + if (name[0] == 'F') // Ignore forward and FIFO pins + return TMG_IGNORE; + for (auto c : boost::adaptors::reverse(name)) { + if (std::isdigit(c) || c == 'X' || c == '[' || c == ']') + continue; + if (c == 'A' || c == 'B') + clockInfoCount = 1; + else + NPNR_ASSERT_FALSE_STR("bad ram port"); + return (cell->ports.at(port).type == PORT_OUT) ? TMG_REGISTER_OUTPUT : TMG_REGISTER_INPUT; + } + NPNR_ASSERT_FALSE_STR("no timing type for RAM port '" + port.str(ctx) + "'"); + } else { + log_error("cell type '%s' is unsupported (instantiated as '%s')\n", cell->type.c_str(ctx), + cell->name.c_str(ctx)); + } +} + +TimingClockingInfo GateMateImpl::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const +{ + TimingClockingInfo info; + info.setup = DelayPair(0); + info.hold = DelayPair(0); + info.clockToQ = DelayQuad(0); + if (cell->type.in(id_CPE_FF, id_CPE_FF_L, id_CPE_FF_U, id_CPE_LATCH)) { + bool inverted = int_or_default(cell->params, id_C_CPE_CLK, 0) == 0b01; + info.edge = inverted ? FALLING_EDGE : RISING_EDGE; + info.clock_port = id_CLK; + if (port.in(id_DIN, id_EN, id_SR)) + get_setuphold_from_tmg_db(id_timing_del_Setup_D_L, id_timing_del_Hold_D_L, info.setup, info.hold); + if (port.in(id_DOUT)) { + bool is_upper = (cell->bel != BelId()) && (ctx->getBelLocation(cell->bel).z == CPE_LT_U_Z); + get_delay_from_tmg_db(id_timing__SEQ_CLK_FF1_Q, info.clockToQ); + DelayQuad delay = DelayQuad{0}; + get_delay_from_tmg_db(is_upper ? id_timing_Q2_OUT2 : id_timing_Q1_OUT1, delay); + info.clockToQ += delay; + get_delay_from_tmg_db(id_timing_del_CPE_CP_Q, delay); + info.clockToQ += delay; + } + } else if (cell->type == id_RAM) { + std::string name = port.str(ctx); + if (boost::starts_with(name, "CLOCK")) + get_delay_from_tmg_db(id_timing_RAM_NOECC_IOPATH_1, info.clockToQ); + if (boost::starts_with(name, "DOA")) + get_delay_from_tmg_db(id_timing_RAM_NOECC_IOPATH_2, info.clockToQ); + if (boost::starts_with(name, "DOB")) + get_delay_from_tmg_db(id_timing_RAM_NOECC_IOPATH_3, info.clockToQ); + if (boost::starts_with(name, "ECC")) + get_delay_from_tmg_db(id_timing_RAM_NOECC_IOPATH_4, info.clockToQ); + if (boost::starts_with(name, "ADDR")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_1, info.setup, info.hold); + if (boost::starts_with(name, "CLOCK1")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_2, info.setup, info.hold); + if (boost::starts_with(name, "DIA")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_3, info.setup, info.hold); + if (boost::starts_with(name, "DIB")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_4, info.setup, info.hold); + if (boost::starts_with(name, "ENA")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_5, info.setup, info.hold); + if (boost::starts_with(name, "ENB")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_6, info.setup, info.hold); + if (boost::starts_with(name, "GLWEA")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_7, info.setup, info.hold); + if (boost::starts_with(name, "GLWEB")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_8, info.setup, info.hold); + if (boost::starts_with(name, "WEA")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_9, info.setup, info.hold); + if (boost::starts_with(name, "WEB")) + get_setuphold_from_tmg_db(id_timing_RAM_NOECC_SETUPHOLD_10, info.setup, info.hold); + bool is_clk_b = false; + for (auto c : boost::adaptors::reverse(name)) { + if (std::isdigit(c) || c == 'X' || c == '[' || c == ']') + continue; + if (c == 'A') + is_clk_b = false; + else if (c == 'B') + is_clk_b = true; + else + NPNR_ASSERT_FALSE_STR("bad ram port"); + break; + } + + bool inverted = int_or_default(cell->params, id_A_CLK_INV, 0); + if (is_clk_b) + inverted = int_or_default(cell->params, id_B_CLK_INV, 0); + + info.edge = inverted ? FALLING_EDGE : RISING_EDGE; + // TODO: Fix which clock is actually used + info.clock_port = is_clk_b ? id_CLOCK1 : id_CLOCK1; + } + + return info; +} + +NEXTPNR_NAMESPACE_END diff --git a/himbaechel/uarch/gatemate/extra_data.h b/himbaechel/uarch/gatemate/extra_data.h index 8ce126dc..9252a389 100644 --- a/himbaechel/uarch/gatemate/extra_data.h +++ b/himbaechel/uarch/gatemate/extra_data.h @@ -62,6 +62,13 @@ NPNR_PACKED_STRUCT(struct GateMatePadExtraDataPOD { uint16_t dummy; }); +NPNR_PACKED_STRUCT(struct GateMateTimingExtraDataPOD { + int32_t name; + TimingValue delay; +}); + +NPNR_PACKED_STRUCT(struct GateMateSpeedGradeExtraDataPOD { RelSlice timings; }); + enum MuxFlags { MUX_INVERT = 1, diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index 6f17d1c5..73bc7b33 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -30,14 +30,72 @@ NEXTPNR_NAMESPACE_BEGIN GateMateImpl::~GateMateImpl() {}; +static int parse_mode(const std::string &val, const std::map &map, const char *error_msg) +{ + try { + int i = std::stoi(val); + if (i >= 1 && i <= 3) + return i; + } catch (...) { + auto it = map.find(val); + if (it != map.end()) + return it->second; + } + log_error("%s\n", error_msg); +} + void GateMateImpl::init_database(Arch *arch) { const ArchArgs &args = arch->args; init_uarch_constids(arch); arch->load_chipdb(stringf("gatemate/chipdb-%s.bin", args.device.c_str())); arch->set_package("FBGA324"); - arch->set_speed_grade("DEFAULT"); dies = std::stoi(args.device.substr(6)); + fpga_mode = 3; + timing_mode = 3; + + static const std::map fpga_map = {{"best", 1}, {"typical", 2}, {"worst", 3}}; + static const std::map timing_map = {{"lowpower", 1}, {"economy", 2}, {"speed", 3}}; + + if (args.options.count("fpga_mode")) + fpga_mode = parse_mode(args.options.at("fpga_mode"), fpga_map, + "timing mode valid values are {1:best, 2:typical, 3:worst}"); + if (args.options.count("time_mode")) + timing_mode = parse_mode(args.options.at("time_mode"), timing_map, + "operation mode valid values are {1:lowpower, 2:economy, 3:speed}"); + + std::string speed_grade = ""; + switch (fpga_mode) { + case 1: + speed_grade = "best_"; + break; + case 2: + speed_grade = "typ_"; + break; + default: + speed_grade = "worst_"; + break; + } + log_info("Using timing mode '%s'\n", fpga_mode == 1 ? "BEST" + : fpga_mode == 2 ? "TYPICAL" + : fpga_mode == 3 ? "WORST" + : ""); + + switch (timing_mode) { + case 1: + speed_grade += "lpr"; + break; + case 2: + speed_grade += "eco"; + break; + default: + speed_grade += "spd"; + } + log_info("Using operation mode '%s'\n", timing_mode == 1 ? "LOWPOWER" + : timing_mode == 2 ? "ECONOMY" + : timing_mode == 3 ? "SPEED" + : ""); + arch->set_speed_grade(speed_grade); } const GateMateTileExtraDataPOD *GateMateImpl::tile_extra_data(int tile) const @@ -68,15 +126,10 @@ void GateMateImpl::init(Context *ctx) ctx->getBelLocation(bel)); } } -} - -delay_t GateMateImpl::estimateDelay(WireId src, WireId dst) const -{ - int sx, sy, dx, dy; - tile_xy(ctx->chip_info, src.tile, sx, sy); - tile_xy(ctx->chip_info, dst.tile, dx, dy); - - return 100 + 100 * (std::abs(dx - sx) + std::abs(dy - sy)); + const auto &sp = reinterpret_cast(ctx->speed_grade->extra_data.get()); + for (int i = 0; i < sp->timings.ssize(); i++) { + timing.emplace(IdString(sp->timings[i].name), &sp->timings[i]); + } } bool GateMateImpl::isBelLocationValid(BelId bel, bool explain_invalid) const @@ -181,29 +234,28 @@ bool GateMateImpl::getClusterPlacement(ClusterId cluster, BelId root_bel, void GateMateImpl::prePlace() { assign_cell_info(); } -void GateMateImpl::postPlace() { repack(); } +void GateMateImpl::postPlace() +{ + repack(); + ctx->assignArchInfo(); +} void GateMateImpl::preRoute() { - ctx->assignArchInfo(); route_mult(); route_clock(); + ctx->assignArchInfo(); } void GateMateImpl::postRoute() { - ctx->assignArchInfo(); - const ArchArgs &args = ctx->args; if (args.options.count("out")) { write_bitstream(args.device, args.options.at("out")); } } -void GateMateImpl::configurePlacerHeap(PlacerHeapCfg &cfg) -{ - cfg.placeAllAtOnce = true; -} +void GateMateImpl::configurePlacerHeap(PlacerHeapCfg &cfg) { cfg.placeAllAtOnce = true; } int GateMateImpl::get_dff_config(CellInfo *dff) const { diff --git a/himbaechel/uarch/gatemate/gatemate.h b/himbaechel/uarch/gatemate/gatemate.h index ae280461..f7b0e51e 100644 --- a/himbaechel/uarch/gatemate/gatemate.h +++ b/himbaechel/uarch/gatemate/gatemate.h @@ -46,6 +46,9 @@ struct GateMateImpl : HimbaechelAPI bool isBelLocationValid(BelId bel, bool explain_invalid = false) const override; delay_t estimateDelay(WireId src, WireId dst) const override; + bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const override; + TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const override; + TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const override; void drawBel(std::vector &g, GraphicElement::style_t style, IdString bel_type, Loc loc) override; @@ -75,6 +78,9 @@ struct GateMateImpl : HimbaechelAPI pool multiplier_a_passthru_lowers; pool multiplier_a_passthru_uppers; pool multiplier_zero_drivers; + std::vector multipliers; + int fpga_mode; + int timing_mode; private: bool getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc, @@ -91,6 +97,10 @@ struct GateMateImpl : HimbaechelAPI const GateMateBelExtraDataPOD *bel_extra_data(BelId bel) const; + bool get_delay_from_tmg_db(IdString id, DelayQuad &delay) const; + void get_setuphold_from_tmg_db(IdString id_setup, IdString id_hold, DelayPair &setup, DelayPair &hold) const; + void get_setuphold_from_tmg_db(IdString id_setuphold, DelayPair &setup, DelayPair &hold) const; + struct GateMateCellInfo { // slice info @@ -101,6 +111,7 @@ struct GateMateImpl : HimbaechelAPI }; std::vector fast_cell_info; std::map> pin_to_constr; + std::map timing; }; NEXTPNR_NAMESPACE_END diff --git a/himbaechel/uarch/gatemate/gen/arch_gen.py b/himbaechel/uarch/gatemate/gen/arch_gen.py index 6c70cf03..522e726c 100644 --- a/himbaechel/uarch/gatemate/gen/arch_gen.py +++ b/himbaechel/uarch/gatemate/gen/arch_gen.py @@ -18,6 +18,7 @@ import os from os import path +import re import sys import argparse @@ -41,6 +42,9 @@ sys.path += args.lib import chip import die +pip_tmg_names = set() +node_tmg_names = set() + @dataclass class TileExtraData(BBAStruct): die : int = 0 @@ -130,103 +134,64 @@ class PadExtraData(BBAStruct): bba.u16(self.z) bba.u16(0) +@dataclass +class TimingExtraData(BBAStruct): + name: IdString + delay: TimingValue = field(default_factory=TimingValue) + + def serialise_lists(self, context: str, bba: BBAWriter): + pass + def serialise(self, context: str, bba: BBAWriter): + bba.u32(self.name.index) + self.delay.serialise(context, bba) + +@dataclass +class SpeedGradeExtraData(BBAStruct): + timings: list[TimingExtraData] = field(default_factory = list) + + def add_timing(self, name: IdString, delay: TimingValue): + item = TimingExtraData(name,delay) + self.timings.append(item) + + def serialise_lists(self, context: str, bba: BBAWriter): + bba.label(f"{context}_timings") + for i, t in enumerate(self.timings): + t.serialise(f"{context}_timing{i}", bba) + pass + def serialise(self, context: str, bba: BBAWriter): + bba.slice(f"{context}_timings", len(self.timings)) + +def convert_timing(tim): + return TimingValue(tim.rise.min, tim.rise.max, tim.fall.min, tim.fall.max) + def set_timings(ch): - speed = "DEFAULT" - tmg = ch.set_speed_grades([speed]) - - lut = ch.timing.add_cell_variant(speed, "CPE_LT_L") - lut.add_comb_arc("IN1", "OUT", TimingValue(416, 418)) # IN5 to OUT1 - lut.add_comb_arc("IN2", "OUT", TimingValue(413, 422)) # IN6 to OUT1 - lut.add_comb_arc("IN3", "OUT", TimingValue(372, 374)) # IN7 to OUT1 - lut.add_comb_arc("IN4", "OUT", TimingValue(275, 385)) # IN8 to OUT1 - - lut = ch.timing.add_cell_variant(speed, "CPE_LT_U") - lut.add_comb_arc("IN1", "OUT", TimingValue(479, 484)) # to OUT2 - lut.add_comb_arc("IN2", "OUT", TimingValue(471, 488)) # to OUT2 - lut.add_comb_arc("IN3", "OUT", TimingValue(446, 449)) # to OUT2 - lut.add_comb_arc("IN4", "OUT", TimingValue(443, 453)) # to OUT2 - - lut = ch.timing.add_cell_variant(speed, "CPE_LT") - lut.add_comb_arc("IN1", "OUT", TimingValue(479, 484)) # to OUT2 - lut.add_comb_arc("IN2", "OUT", TimingValue(471, 488)) # to OUT2 - lut.add_comb_arc("IN3", "OUT", TimingValue(446, 449)) # to OUT2 - lut.add_comb_arc("IN4", "OUT", TimingValue(443, 453)) # to OUT2 - - lut = ch.timing.add_cell_variant(speed, "CPE_L2T4") - lut.add_comb_arc("IN1", "OUT", TimingValue(479, 484)) # to OUT2 - lut.add_comb_arc("IN2", "OUT", TimingValue(471, 488)) # to OUT2 - lut.add_comb_arc("IN3", "OUT", TimingValue(446, 449)) # to OUT2 - lut.add_comb_arc("IN4", "OUT", TimingValue(443, 453)) # to OUT2 - - lut = ch.timing.add_cell_variant(speed, "CPE_L2T5") - lut.add_comb_arc("IN1", "OUT1", TimingValue(479, 484)) # to OUT2 - lut.add_comb_arc("IN2", "OUT1", TimingValue(471, 488)) # to OUT2 - lut.add_comb_arc("IN3", "OUT1", TimingValue(446, 449)) # to OUT2 - lut.add_comb_arc("IN4", "OUT1", TimingValue(443, 453)) # to OUT2 - lut.add_comb_arc("IN5", "OUT1", TimingValue(416, 418)) # IN5 to OUT1 - lut.add_comb_arc("IN6", "OUT1", TimingValue(413, 422)) # IN6 to OUT1 - lut.add_comb_arc("IN7", "OUT1", TimingValue(372, 374)) # IN7 to OUT1 - lut.add_comb_arc("IN8", "OUT1", TimingValue(275, 385)) # IN8 to OUT1 - - lut = ch.timing.add_cell_variant(speed, "CPE_MX4") - lut.add_comb_arc("IN1", "OUT1", TimingValue(479, 484)) # to OUT2 - lut.add_comb_arc("IN2", "OUT1", TimingValue(471, 488)) # to OUT2 - lut.add_comb_arc("IN3", "OUT1", TimingValue(446, 449)) # to OUT2 - lut.add_comb_arc("IN4", "OUT1", TimingValue(443, 453)) # to OUT2 - lut.add_comb_arc("IN5", "OUT1", TimingValue(416, 418)) # IN5 to OUT1 - lut.add_comb_arc("IN6", "OUT1", TimingValue(413, 422)) # IN6 to OUT1 - lut.add_comb_arc("IN7", "OUT1", TimingValue(372, 374)) # IN7 to OUT1 - lut.add_comb_arc("IN8", "OUT1", TimingValue(275, 385)) # IN8 to OUT1 - - lut = ch.timing.add_cell_variant(speed, "CPE_CI") - lut.add_comb_arc("IN1", "COUTY1", TimingValue(479, 484)) # to OUT2 - lut.add_comb_arc("IN2", "COUTY1", TimingValue(471, 488)) # to OUT2 - lut.add_comb_arc("IN3", "COUTY1", TimingValue(446, 449)) # to OUT2 - lut.add_comb_arc("IN4", "COUTY1", TimingValue(443, 453)) # to OUT2 - - lut = ch.timing.add_cell_variant(speed, "CPE_EN_CIN") - lut.add_comb_arc("CINY1", "OUT1", TimingValue(479, 484)) # to OUT2 - - lut = ch.timing.add_cell_variant(speed, "CPE_ADDF") - lut.add_comb_arc("IN1", "OUT2", TimingValue(479, 484)) # to OUT2 - lut.add_comb_arc("IN2", "OUT2", TimingValue(471, 488)) # to OUT2 - lut.add_comb_arc("IN3", "OUT2", TimingValue(446, 449)) # to OUT2 - lut.add_comb_arc("IN4", "OUT2", TimingValue(443, 453)) # to OUT2 - lut.add_comb_arc("IN5", "OUT1", TimingValue(416, 418)) # IN5 to OUT1 - lut.add_comb_arc("IN6", "OUT1", TimingValue(413, 422)) # IN6 to OUT1 - lut.add_comb_arc("IN7", "OUT1", TimingValue(372, 374)) # IN7 to OUT1 - lut.add_comb_arc("IN8", "OUT1", TimingValue(275, 385)) # IN8 to OUT1 - lut.add_comb_arc("CINY1", "COUTY1", TimingValue(479, 484)) - - lut = ch.timing.add_cell_variant(speed, "CPE_ADDF2") - lut.add_comb_arc("IN1", "OUT2", TimingValue(479, 484)) # to OUT2 - lut.add_comb_arc("IN2", "OUT2", TimingValue(471, 488)) # to OUT2 - lut.add_comb_arc("IN3", "OUT2", TimingValue(446, 449)) # to OUT2 - lut.add_comb_arc("IN4", "OUT2", TimingValue(443, 453)) # to OUT2 - lut.add_comb_arc("IN5", "OUT1", TimingValue(416, 418)) # IN5 to OUT1 - lut.add_comb_arc("IN6", "OUT1", TimingValue(413, 422)) # IN6 to OUT1 - lut.add_comb_arc("IN7", "OUT1", TimingValue(372, 374)) # IN7 to OUT1 - lut.add_comb_arc("IN8", "OUT1", TimingValue(275, 385)) # IN8 to OUT1 - lut.add_comb_arc("CINY1", "COUTY1", TimingValue(479, 484)) - - dff = ch.timing.add_cell_variant(speed, "CPE_FF") - dff.add_setup_hold("CLK", "DIN", ClockEdge.RISING, TimingValue(60), TimingValue(50)) - dff.add_clock_out("CLK", "DOUT", ClockEdge.RISING, TimingValue(60)) - - dff = ch.timing.add_cell_variant(speed, "CPE_LATCH") - dff.add_setup_hold("CLK", "DIN", ClockEdge.RISING, TimingValue(60), TimingValue(50)) - dff.add_clock_out("CLK", "DOUT", ClockEdge.RISING, TimingValue(60)) - - lut = ch.timing.add_cell_variant(speed, "CPE_RAMI") - lut.add_comb_arc("RAM_I", "OUT", TimingValue(0, 0)) - - lut = ch.timing.add_cell_variant(speed, "CPE_RAMO") - lut.add_comb_arc("I", "RAM_O", TimingValue(0, 0)) - - lut = ch.timing.add_cell_variant(speed, "CPE_RAMIO") - #lut.add_comb_arc("I", "OUT", TimingValue(0, 0)) - lut.add_comb_arc("I", "RAM_O", TimingValue(0, 0)) - lut.add_comb_arc("RAM_I", "OUT", TimingValue(0, 0)) + speed_grades = ["best_lpr", "best_eco", "best_spd", + "typ_lpr", "typ_eco", "typ_spd", + "worst_lpr", "worst_eco", "worst_spd"] + rename_table = { + "CINX_OUT1": "_ARBLUT_CINX_OUT1", + "CINX_OUT2": "_ARBLUT_CINX_OUT2", + "PINX_OUT1": "_ARBLUT_PINX_OUT1", + "PINX_OUT2": "_ARBLUT_PINX_OUT2", + "PINY1_OUT1": "_ARBLUT_PINY1_OUT1", + "PINY1_OUT2": "_ARBLUT_PINY1_OUT2", + } + tmg = ch.set_speed_grades(speed_grades) + for speed in speed_grades: + print(f"Loading timings for {speed}...") + timing = dict(sorted(chip.get_timings(speed).items())) + tmg.get_speed_grade(speed).extra_data = SpeedGradeExtraData() + for name, val in timing.items(): + if name.startswith(("sb_del_t", "im_x", "om_x", "sb_rim_xy", "edge_xy")): + continue + name = "timing_" + re.sub(r"[-= >]", "_", rename_table.get(name, name)) + tmg.get_speed_grade(speed).extra_data.add_timing(name=ch.strs.id(name), delay=convert_timing(val)) + #for k in node_tmg_names: + # assert k in timing, f"node class {k} not found in timing data" + # tmg.set_node_class(grade=speed, name=k, delay=convert_timing(timing[k])) + #for k in pip_tmg_names: + # assert k in timing, f"pip class {k} not found in timing data" + # tmg.set_pip_class(grade=speed, name=k, delay=convert_timing(timing[k])) EXPECTED_VERSION = 1.4 @@ -277,7 +242,9 @@ def main(): for pin in sorted(die.get_primitive_pins(prim.type)): tt.add_bel_pin(bel, pin.name, die.get_pin_connection_name(prim,pin), pin.dir) for mux in sorted(die.get_mux_connections_for_type(type_name)): - pp = tt.create_pip(mux.src, mux.dst) + if len(mux.delay)>0: + pip_tmg_names.add(mux.delay) + pp = tt.create_pip(mux.src, mux.dst, mux.delay) if mux.name: mux_flags = MUX_INVERT if mux.invert else 0 mux_flags |= MUX_VISIBLE if mux.visible else 0 @@ -301,9 +268,14 @@ def main(): # Create nodes between tiles for _,nodes in dev.get_connections(): node = [] + timing = "" for conn in sorted(nodes): node.append(NodeWire(conn.x + 2, conn.y + 2, conn.name)) - ch.add_node(node) + # for now update to last one we have defined + if len(conn.delay)>0: + timing = conn.delay + node_tmg_names.add(conn.delay) + ch.add_node(node, timing) set_timings(ch) for package in dev.get_packages(): diff --git a/himbaechel/uarch/gatemate/pack_clocking.cc b/himbaechel/uarch/gatemate/pack_clocking.cc index 1a39c261..32394dc0 100644 --- a/himbaechel/uarch/gatemate/pack_clocking.cc +++ b/himbaechel/uarch/gatemate/pack_clocking.cc @@ -336,6 +336,18 @@ void GateMatePacker::remove_clocking() flush_cells(); } +static const char *fpga_mode_to_str(int mode) +{ + switch (mode) { + case 1: + return "LOWPOWER"; + case 2: + return "ECONOMY"; + default: + return "SPEED"; + } +} + void GateMatePacker::pack_pll() { std::vector pll_index(uarch->dies); @@ -465,6 +477,10 @@ void GateMatePacker::pack_pll() log_error("Unknown PERF_MD parameter value '%s' for cell %s.\n", mode.c_str(), ci.name.c_str(ctx)); } + if (perf_md != uarch->fpga_mode) + log_warning("PLL '%s' mode is '%s' but FPGA mode is '%s'.\n", ci.name.c_str(ctx), + fpga_mode_to_str(perf_md), fpga_mode_to_str(uarch->fpga_mode)); + double ref_clk = double_or_default(ci.params, id_REF_CLK, 0.0); if (ref_clk <= 0 || ref_clk > 125) log_error("REF_CLK parameter is out of range (0,125.00].\n");