diff --git a/ecp5/arch.cc b/ecp5/arch.cc index e3b8d65a..39d2ba17 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -1071,24 +1071,11 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port "INV") ? FALLING_EDGE : RISING_EDGE; - - // REGMODE determines some timing parameters - nextpnr_ecp5::IdString regmode_timing; - if (!cell->ramInfo.output_a_registered && !cell->ramInfo.output_b_registered) { - regmode_timing = id_DP16KD_REGMODE_A_NOREG_REGMODE_B_NOREG; - } else if (!cell->ramInfo.output_a_registered && cell->ramInfo.output_b_registered) { - regmode_timing = id_DP16KD_REGMODE_A_NOREG_REGMODE_B_OUTREG; - } else if (cell->ramInfo.output_a_registered && !cell->ramInfo.output_b_registered) { - regmode_timing = id_DP16KD_REGMODE_A_OUTREG_REGMODE_B_NOREG; - } else if (cell->ramInfo.output_a_registered && cell->ramInfo.output_b_registered) { - regmode_timing = id_DP16KD_REGMODE_A_OUTREG_REGMODE_B_OUTREG; - } - if (cell->ports.at(port).type == PORT_OUT) { - bool is_path = getDelayFromTimingDatabase(regmode_timing, half_clock, port, info.clockToQ); + bool is_path = getDelayFromTimingDatabase(cell->ramInfo.regmode_timing_id, half_clock, port, info.clockToQ); NPNR_ASSERT(is_path); } else { - getSetupHoldFromTimingDatabase(regmode_timing, half_clock, port, info.setup, info.hold); + getSetupHoldFromTimingDatabase(cell->ramInfo.regmode_timing_id, half_clock, port, info.setup, info.hold); } } else if (cell->type == id_DCUA) { std::string prefix = port.str(this).substr(0, 9); diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h index 5312045c..0f197345 100644 --- a/ecp5/archdefs.h +++ b/ecp5/archdefs.h @@ -180,8 +180,14 @@ struct ArchCellInfo struct { bool is_pdp; - bool output_a_registered; - bool output_b_registered; + // Are the outputs from a DP16KD registered (OUTREG) + // or non-registered (NOREG) + bool is_output_a_registered; + bool is_output_b_registered; + // Which timing information to use for a DP16KD. Depends on registering + // configuration. + nextpnr_ecp5::IdString regmode_timing_id; + } ramInfo; }; diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 16728af4..11aef630 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -3012,8 +3012,19 @@ void Arch::assignArchInfo() std::string regmode_b = str_or_default(ci->params, id("REGMODE_B"), "NOREG"); if (!(regmode_b == "NOREG" || regmode_b == "OUTREG")) NPNR_ASSERT_FALSE_STR("bad DP16KD REGMODE_B configuration '" + regmode_b + "'"); - ci->ramInfo.output_a_registered = regmode_a == "OUTREG"; - ci->ramInfo.output_b_registered = regmode_b == "OUTREG"; + ci->ramInfo.is_output_a_registered = regmode_a == "OUTREG"; + ci->ramInfo.is_output_b_registered = regmode_b == "OUTREG"; + + // Based on the REGMODE, we have different timing lookup tables. + if (!ci->ramInfo.is_output_a_registered && !ci->ramInfo.is_output_b_registered) { + ci->ramInfo.regmode_timing_id = id_DP16KD_REGMODE_A_NOREG_REGMODE_B_NOREG; + } else if (!ci->ramInfo.is_output_a_registered && ci->ramInfo.is_output_b_registered) { + ci->ramInfo.regmode_timing_id = id_DP16KD_REGMODE_A_NOREG_REGMODE_B_OUTREG; + } else if (ci->ramInfo.is_output_a_registered && !ci->ramInfo.is_output_b_registered) { + ci->ramInfo.regmode_timing_id = id_DP16KD_REGMODE_A_OUTREG_REGMODE_B_NOREG; + } else if (ci->ramInfo.is_output_a_registered && ci->ramInfo.is_output_b_registered) { + ci->ramInfo.regmode_timing_id = id_DP16KD_REGMODE_A_OUTREG_REGMODE_B_OUTREG; + } } } for (auto net : sorted(nets)) {