aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorRoss Schlaikjer <ross@schlaikjer.net>2020-04-07 14:03:55 -0400
committerRoss Schlaikjer <ross@schlaikjer.net>2020-04-07 14:03:55 -0400
commit0bdf1e05f126e01adcea3f11d1d76f3235ab44e8 (patch)
treeb8c247e05ed73492f2dda5dd3b86e47f24c8642c /ecp5
parentc00746316854566d82694a5ab1811ebb9bb7685d (diff)
downloadnextpnr-0bdf1e05f126e01adcea3f11d1d76f3235ab44e8.tar.gz
nextpnr-0bdf1e05f126e01adcea3f11d1d76f3235ab44e8.tar.bz2
nextpnr-0bdf1e05f126e01adcea3f11d1d76f3235ab44e8.zip
Extract regmode configuration to ArchInfo
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/arch.cc12
-rw-r--r--ecp5/archdefs.h2
-rw-r--r--ecp5/pack.cc10
3 files changed, 16 insertions, 8 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 548b8d4f..e3b8d65a 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -1073,19 +1073,15 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
: RISING_EDGE;
// REGMODE determines some timing parameters
- auto regmode_a = str_or_default(cell->params, id("REGMODE_A"), "NOREG");
- auto regmode_b = str_or_default(cell->params, id("REGMODE_B"), "NOREG");
nextpnr_ecp5::IdString regmode_timing;
- if (regmode_a == "NOREG" && regmode_b == "NOREG") {
+ if (!cell->ramInfo.output_a_registered && !cell->ramInfo.output_b_registered) {
regmode_timing = id_DP16KD_REGMODE_A_NOREG_REGMODE_B_NOREG;
- } else if (regmode_a == "NOREG" && regmode_b == "OUTREG") {
+ } else if (!cell->ramInfo.output_a_registered && cell->ramInfo.output_b_registered) {
regmode_timing = id_DP16KD_REGMODE_A_NOREG_REGMODE_B_OUTREG;
- } else if (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_NOREG;
- } else if (regmode_a == "OUTREG" && regmode_b == "OUTREG") {
+ } else if (cell->ramInfo.output_a_registered && cell->ramInfo.output_b_registered) {
regmode_timing = id_DP16KD_REGMODE_A_OUTREG_REGMODE_B_OUTREG;
- } else {
- NPNR_ASSERT_FALSE_STR("bad DP16KD REGMODE configuration: " + regmode_a + ", " + regmode_b);
}
if (cell->ports.at(port).type == PORT_OUT) {
diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h
index b176eec0..5312045c 100644
--- a/ecp5/archdefs.h
+++ b/ecp5/archdefs.h
@@ -180,6 +180,8 @@ struct ArchCellInfo
struct
{
bool is_pdp;
+ bool output_a_registered;
+ bool output_b_registered;
} ramInfo;
};
diff --git a/ecp5/pack.cc b/ecp5/pack.cc
index f5e8a544..16728af4 100644
--- a/ecp5/pack.cc
+++ b/ecp5/pack.cc
@@ -3004,6 +3004,16 @@ 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"))
+ NPNR_ASSERT_FALSE_STR("bad DP16KD REGMODE_A configuration '" + regmode_a + "'");
+ 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";
}
}
for (auto net : sorted(nets)) {