mirror of https://github.com/YosysHQ/nextpnr.git
gatemate: add iopath delays (#1537)
* Timing * clangformat * Import some new data * Import all timing data * Add constants for needed timings * Add separate file for delay handling * wip * Added helpers * wip * proper place for assignArchInfo * wip * wip * Fixes for IO * Add IOSEL delays * Fix logic loops * help figure out some ram paths * return true only if exists * cover all primitives * Disable not used paths * clockToQ * Added some RAM timings * Add more IOPATHs * cleanup * cleanup * Map few more timings * remove short name options * support strings as options * no need for return
This commit is contained in:
parent
e598b2f4d9
commit
6a598b945e
|
|
@ -5,6 +5,7 @@ set(SOURCES
|
|||
config.cc
|
||||
config.h
|
||||
constids.inc
|
||||
delay.cc
|
||||
extra_data.h
|
||||
gatemate.cc
|
||||
gatemate.h
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 <boost/algorithm/string.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
#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<IdString, IdString> map_upper = {
|
||||
{id_OUT, id_OUT2},
|
||||
{id_RAM_O, id_RAM_O2},
|
||||
{id_RAM_I, id_RAM_I2},
|
||||
{id_CPOUT, id_CPOUT2},
|
||||
};
|
||||
static dict<IdString, IdString> 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
|
||||
|
|
@ -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<GateMateTimingExtraDataPOD> timings; });
|
||||
|
||||
enum MuxFlags
|
||||
{
|
||||
MUX_INVERT = 1,
|
||||
|
|
|
|||
|
|
@ -30,14 +30,72 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||
|
||||
GateMateImpl::~GateMateImpl() {};
|
||||
|
||||
static int parse_mode(const std::string &val, const std::map<std::string, int> &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<std::string, int> fpga_map = {{"best", 1}, {"typical", 2}, {"worst", 3}};
|
||||
static const std::map<std::string, int> 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<const GateMateSpeedGradeExtraDataPOD *>(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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<GraphicElement> &g, GraphicElement::style_t style, IdString bel_type, Loc loc) override;
|
||||
|
||||
|
|
@ -75,6 +78,9 @@ struct GateMateImpl : HimbaechelAPI
|
|||
pool<IdString> multiplier_a_passthru_lowers;
|
||||
pool<IdString> multiplier_a_passthru_uppers;
|
||||
pool<IdString> multiplier_zero_drivers;
|
||||
std::vector<CellInfo *> 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<GateMateCellInfo> fast_cell_info;
|
||||
std::map<BelId, std::map<IdString, const GateMateBelPinConstraintPOD *>> pin_to_constr;
|
||||
std::map<IdString, const GateMateTimingExtraDataPOD *> timing;
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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<int> 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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue