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:
Miodrag Milanović 2025-08-22 11:07:34 +02:00 committed by GitHub
parent e598b2f4d9
commit 6a598b945e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 1244 additions and 116 deletions

View File

@ -5,6 +5,7 @@ set(SOURCES
config.cc
config.h
constids.inc
delay.cc
extra_data.h
gatemate.cc
gatemate.h

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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
{

View File

@ -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

View File

@ -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():

View File

@ -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");