Merge pull request #423 from rschlaikjer/rschlaikjer-regmode-timing-database
Add support for REGMODE to DP16KD
This commit is contained in:
commit
396dfb7d5e
@ -1077,12 +1077,10 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
|
|||||||
? FALLING_EDGE
|
? FALLING_EDGE
|
||||||
: RISING_EDGE;
|
: RISING_EDGE;
|
||||||
if (cell->ports.at(port).type == PORT_OUT) {
|
if (cell->ports.at(port).type == PORT_OUT) {
|
||||||
bool is_path = getDelayFromTimingDatabase(id_DP16KD_REGMODE_A_NOREG_REGMODE_B_NOREG, half_clock, port,
|
bool is_path = getDelayFromTimingDatabase(cell->ramInfo.regmode_timing_id, half_clock, port, info.clockToQ);
|
||||||
info.clockToQ);
|
|
||||||
NPNR_ASSERT(is_path);
|
NPNR_ASSERT(is_path);
|
||||||
} else {
|
} else {
|
||||||
getSetupHoldFromTimingDatabase(id_DP16KD_REGMODE_A_NOREG_REGMODE_B_NOREG, half_clock, port, info.setup,
|
getSetupHoldFromTimingDatabase(cell->ramInfo.regmode_timing_id, half_clock, port, info.setup, info.hold);
|
||||||
info.hold);
|
|
||||||
}
|
}
|
||||||
} else if (cell->type == id_DCUA) {
|
} else if (cell->type == id_DCUA) {
|
||||||
std::string prefix = port.str(this).substr(0, 9);
|
std::string prefix = port.str(this).substr(0, 9);
|
||||||
|
@ -180,6 +180,14 @@ struct ArchCellInfo
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool is_pdp;
|
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;
|
} ramInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
23
ecp5/pack.cc
23
ecp5/pack.cc
@ -3014,6 +3014,29 @@ void Arch::assignArchInfo()
|
|||||||
ci->sliceInfo.has_l6mux = true;
|
ci->sliceInfo.has_l6mux = true;
|
||||||
} else if (ci->type == id_DP16KD) {
|
} else if (ci->type == id_DP16KD) {
|
||||||
ci->ramInfo.is_pdp = (int_or_default(ci->params, id("DATA_WIDTH_A"), 0) == 36);
|
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)) {
|
for (auto net : sorted(nets)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user