aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ecp5/arch.cc17
-rw-r--r--ecp5/archdefs.h10
-rw-r--r--ecp5/pack.cc15
3 files changed, 23 insertions, 19 deletions
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)) {