diff options
| author | David Shah <dave@ds0.me> | 2020-04-07 20:02:29 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-07 20:02:29 +0100 | 
| commit | 396dfb7d5ee4d1a559e50ac79fe4e5f2aaeaccbf (patch) | |
| tree | 2886c786853565c048274fd13b0d1b55c6510c14 | |
| parent | e8933f8519768447874167dcb62a6cd2b24a0225 (diff) | |
| parent | 3aecb3b08c20c3dc5055bce035bd2667705ea5b2 (diff) | |
| download | nextpnr-396dfb7d5ee4d1a559e50ac79fe4e5f2aaeaccbf.tar.gz nextpnr-396dfb7d5ee4d1a559e50ac79fe4e5f2aaeaccbf.tar.bz2 nextpnr-396dfb7d5ee4d1a559e50ac79fe4e5f2aaeaccbf.zip  | |
Merge pull request #423 from rschlaikjer/rschlaikjer-regmode-timing-database
Add support for REGMODE to DP16KD
| -rw-r--r-- | ecp5/arch.cc | 6 | ||||
| -rw-r--r-- | ecp5/archdefs.h | 8 | ||||
| -rw-r--r-- | ecp5/pack.cc | 23 | 
3 files changed, 33 insertions, 4 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 3aed3ad4..ab24842e 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -1077,12 +1077,10 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port                              ? FALLING_EDGE                              : RISING_EDGE;          if (cell->ports.at(port).type == PORT_OUT) { -            bool is_path = getDelayFromTimingDatabase(id_DP16KD_REGMODE_A_NOREG_REGMODE_B_NOREG, 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(id_DP16KD_REGMODE_A_NOREG_REGMODE_B_NOREG, 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 b176eec0..0f197345 100644 --- a/ecp5/archdefs.h +++ b/ecp5/archdefs.h @@ -180,6 +180,14 @@ struct ArchCellInfo      struct      {          bool is_pdp; +        // 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 9c3bb617..0872ae58 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -3014,6 +3014,29 @@ void Arch::assignArchInfo()                  ci->sliceInfo.has_l6mux = true;          } else if (ci->type == id_DP16KD) {              ci->ramInfo.is_pdp = (int_or_default(ci->params, id("DATA_WIDTH_A"), 0) == 36); + +            // Output register mode (REGMODE_{A,B}). Valid options are 'NOREG' and 'OUTREG'. +            std::string regmode_a = str_or_default(ci->params, id("REGMODE_A"), "NOREG"); +            if (regmode_a != "NOREG" && regmode_a != "OUTREG") +                log_error("DP16KD %s has invalid REGMODE_A configuration '%s'\n", ci->name.c_str(this), +                          regmode_a.c_str()); +            std::string regmode_b = str_or_default(ci->params, id("REGMODE_B"), "NOREG"); +            if (regmode_b != "NOREG" && regmode_b != "OUTREG") +                log_error("DP16KD %s has invalid REGMODE_B configuration '%s'\n", ci->name.c_str(this), +                          regmode_b.c_str()); +            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)) {  | 
