Add basic PLL support

This commit is contained in:
Miodrag Milanovic 2025-01-17 09:53:27 +01:00
parent b3658c47e0
commit 6ee0098cf9
4 changed files with 130 additions and 0 deletions

View File

@ -138,6 +138,17 @@ struct BitstreamBackend
cc.configs[0].add_word(stringf("GLBOUT.GLB%d_EN",l.z), int_to_bitvector(1,1));
}
break;
case id_PLL.index:
{
Loc l = ctx->getBelLocation(cell.second->bel);
cc.configs[0].add_word(stringf("PLL%d.CLK_OUT_EN",l.z-4), int_to_bitvector(1,1));
cc.configs[0].add_word(stringf("PLL%d.PLL_EN",l.z-4), int_to_bitvector(1,1));
cc.configs[0].add_word(stringf("PLL%d.PLL_RST",l.z-4), int_to_bitvector(1,1));
for (auto &p : params) {
cc.configs[0].add_word(stringf("PLL%d.%s", l.z-4, p.first.c_str(ctx)), p.second.as_bits());
}
}
break;
default:
log_error("Unhandled cell %s of type %s\n", cell.second.get()->name.c_str(ctx),
cell.second->type.c_str(ctx));

View File

@ -134,3 +134,30 @@ X(D2)
X(D3)
X(S0)
X(S1)
X(CC_PLL)
X(CC_PLL_ADV)
X(PLL)
X(CLK_REF)
X(USR_CLK_REF)
X(USR_SEL_A_B)
X(CLK_FEEDBACK)
X(USR_LOCKED_STDY_RST)
X(CLK0)
X(CLK90)
X(CLK180)
X(CLK270)
X(CLK_REF_OUT)
X(USR_PLL_LOCKED_STDY)
X(USR_PLL_LOCKED)
X(REF_CLK)
X(OUT_CLK)
X(PERF_MD)
X(LOCK_REQ)
X(CLK270_DOUB)
X(CLK180_DOUB)
X(LOW_JITTER)
X(CI_FILTER_CONST)
X(CP_FILTER_CONST)
X(PLL_CFG_A)
X(PLL_CFG_B)

View File

@ -17,6 +17,8 @@
*
*/
#include <boost/algorithm/string.hpp>
#include "pack.h"
#define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc"
@ -468,6 +470,94 @@ void GateMatePacker::pack_bufg()
}
}
template <typename KeyType> double double_or_default(const dict<KeyType, Property> &ct, const KeyType &key, double def = 0)
{
auto found = ct.find(key);
if (found == ct.end())
return def;
else {
if (found->second.is_string) {
try {
return std::stod(found->second.as_string());
} catch (std::invalid_argument &e) {
log_error("Expecting numeric value but got '%s'.\n", found->second.as_string().c_str());
}
} else
return double(found->second.as_int64());
}
};
void GateMatePacker::pack_pll()
{
log_info("Packing PLLss..\n");
for (auto &cell : ctx->cells) {
CellInfo &ci = *cell.second;
if (!ci.type.in(id_CC_PLL))
continue;
disconnect_if_gnd(&ci, id_CLK_REF);
disconnect_if_gnd(&ci, id_USR_CLK_REF);
disconnect_if_gnd(&ci, id_CLK_FEEDBACK);
disconnect_if_gnd(&ci, id_USR_LOCKED_STDY_RST);
ci.params[id_LOCK_REQ] = Property(int_or_default(ci.params, id_LOCK_REQ, 1),1);
ci.params[id_CLK180_DOUB] = Property(int_or_default(ci.params, id_CLK180_DOUB, 0),1);
ci.params[id_CLK270_DOUB] = Property(int_or_default(ci.params, id_CLK270_DOUB, 0),1);
std::string mode = str_or_default(ci.params, id_PERF_MD, "SPEED");
boost::algorithm::to_upper(mode);
int perf_md;
if (mode == "LOWPOWER") perf_md = 1;
else if (mode == "ECONOMY") perf_md = 2;
else if (mode == "SPEED") perf_md = 3;
else log_error("Unknown PERF_MD parameter value '%s' for cell %s.\n", mode.c_str(), ci.name.c_str(ctx));
double ref_clk = double_or_default(ci.params, id_REF_CLK, 0.0);
if (ref_clk <= 0 || ref_clk > 125)
log_error("REF_CLK parameter is out of range (0,125.00].\n");
double max_freq = 0.0;
switch(perf_md) {
case 1: max_freq = 250.00; break;
case 2: max_freq = 312.50; break;
case 3: max_freq = 416.75; break;
}
double out_clk = double_or_default(ci.params, id_OUT_CLK, 0.0);
if (out_clk <= 0 || out_clk > max_freq)
log_error("OUT_CLK parameter is out of range (0,%.2lf].\n", max_freq);
// For 10 MHz - > 25 MHz
ci.params[ctx->id("CFG_A.AO_SW")] = Property(0b01000,5);
ci.params[ctx->id("CFG_A.CI_FILTER_CONST")] = Property(0b00010,5);
ci.params[ctx->id("CFG_A.COARSE_TUNE")] = Property(0b100,3);
ci.params[ctx->id("CFG_A.CP_FILTER_CONST")] = Property(0b00100,5);
ci.params[ctx->id("CFG_A.EN_COARSE_TUNE")] = Property(0b1,1);
ci.params[ctx->id("CFG_A.FAST_LOCK")] = Property(0b1,1);
ci.params[ctx->id("CFG_A.FILTER_SHIFT")] = Property(0b10,2);
ci.params[ctx->id("CFG_A.FINE_TUNE")] = Property(0b00011001000,11);
ci.params[ctx->id("CFG_A.K")] = Property(0b000000000001,12);
ci.params[ctx->id("CFG_A.M1")] = Property(0b000010,6);
ci.params[ctx->id("CFG_A.M2")] = Property(0b0000001001,10);
ci.params[ctx->id("CFG_A.N1")] = Property(0b001001,6);
ci.params[ctx->id("CFG_A.N2")] = Property(0b0000001010,10);
ci.params[ctx->id("CFG_A.PDIV0_MUX")] = Property(0b1,1);
ci.params[ctx->id("CFG_A.PDIV1_SEL")] = Property(0b1,1);
ci.params[ctx->id("CFG_A.SAR_LIMIT")] = Property(0b010,3);
// Remove all not propagated parameters
ci.unsetParam(id_PERF_MD);
ci.unsetParam(id_REF_CLK);
ci.unsetParam(id_OUT_CLK);
ci.unsetParam(id_LOW_JITTER);
ci.unsetParam(id_CI_FILTER_CONST);
ci.unsetParam(id_CP_FILTER_CONST);
//ci.unsetParam(id_PLL_CFG_A);
//ci.unsetParam(id_PLL_CFG_B);
ci.type = id_PLL;
}
}
void GateMatePacker::pack_constants()
{
log_info("Packing constants..\n");
@ -517,6 +607,7 @@ void GateMateImpl::pack()
GateMatePacker packer(ctx, this);
packer.pack_constants();
packer.pack_io();
packer.pack_pll();
packer.pack_bufg();
packer.pack_cpe();
packer.remove_constants();

View File

@ -31,6 +31,7 @@ struct GateMatePacker
void pack_io();
void pack_cpe();
void pack_bufg();
void pack_pll();
void pack_constants();
void disconnect_if_gnd(CellInfo *cell, IdString input);