mirror of
https://github.com/YosysHQ/yosys
synced 2025-08-05 02:40:25 +00:00
icell_liberty: flops
This commit is contained in:
parent
95ed267960
commit
fd344e4611
1 changed files with 84 additions and 2 deletions
|
@ -18,19 +18,27 @@
|
||||||
*/
|
*/
|
||||||
#include "kernel/yosys.h"
|
#include "kernel/yosys.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/celltypes.h"
|
||||||
|
#include "kernel/ff.h"
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
struct LibertyStubber {
|
struct LibertyStubber {
|
||||||
CellTypes ct;
|
CellTypes ct;
|
||||||
CellTypes ct_ff;
|
|
||||||
LibertyStubber() {
|
LibertyStubber() {
|
||||||
ct.setup();
|
ct.setup();
|
||||||
ct.setup_internals_ff();
|
ct.setup_internals_ff();
|
||||||
}
|
}
|
||||||
void liberty_prefix(std::ostream& f)
|
void liberty_prefix(std::ostream& f)
|
||||||
{
|
{
|
||||||
|
f << "/*\n";
|
||||||
|
f << stringf("Models interfaces of select Yosys internal cell.\n");
|
||||||
|
f << stringf("Likely contains INCORRECT POLARITIES.\n");
|
||||||
|
f << stringf("Impractical for any simulation, synthesis, or timing.\n");
|
||||||
|
f << stringf("Intended purely for SDC expansion.\n");
|
||||||
|
f << stringf("Do not microwave or tumble dry.\n");
|
||||||
|
f << stringf("Generated by %s\n", yosys_maybe_version());
|
||||||
|
f << "*/\n";
|
||||||
f << "library (yosys) {\n";
|
f << "library (yosys) {\n";
|
||||||
f << "\tinput_threshold_pct_fall : 50;\n";
|
f << "\tinput_threshold_pct_fall : 50;\n";
|
||||||
f << "\tinput_threshold_pct_rise : 50;\n";
|
f << "\tinput_threshold_pct_rise : 50;\n";
|
||||||
|
@ -45,6 +53,76 @@ struct LibertyStubber {
|
||||||
{
|
{
|
||||||
f << "}\n";
|
f << "}\n";
|
||||||
}
|
}
|
||||||
|
struct LibertyItemizer {
|
||||||
|
std::ostream& f;
|
||||||
|
int indent;
|
||||||
|
LibertyItemizer(std::ostream& f) : f(f), indent(0) {};
|
||||||
|
void item(std::string key, std::string val)
|
||||||
|
{
|
||||||
|
f << std::string(indent, '\t') << key << " : \"" << val << "\";\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void liberty_flop(Module* base, Module* derived, std::ostream& f)
|
||||||
|
{
|
||||||
|
auto base_name = base->name.str().substr(1);
|
||||||
|
auto derived_name = derived->name.str().substr(1);
|
||||||
|
|
||||||
|
FfTypeData ffType(base_name);
|
||||||
|
LibertyItemizer i(f);
|
||||||
|
|
||||||
|
if (ffType.has_gclk) {
|
||||||
|
log_warning("Formal flip flop %s can't be modeled\n", base_name.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ffType.has_ce) {
|
||||||
|
log_warning("DFFE %s can't be modeled\n", base_name.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f << "\tcell (\"" << derived_name << "\") {\n";
|
||||||
|
auto& base_type = ct.cell_types[base_name];
|
||||||
|
i.indent = 3;
|
||||||
|
for (auto x : derived->ports) {
|
||||||
|
bool is_input = base_type.inputs.count(x);
|
||||||
|
bool is_output = base_type.outputs.count(x);
|
||||||
|
f << "\t\tpin (" << RTLIL::unescape_id(x.str()) << ") {\n";
|
||||||
|
if (is_input && !is_output) {
|
||||||
|
i.item("direction", "input");
|
||||||
|
} else if (!is_input && is_output) {
|
||||||
|
i.item("direction", "output");
|
||||||
|
} else {
|
||||||
|
i.item("direction", "inout");
|
||||||
|
}
|
||||||
|
if (RTLIL::unescape_id(x) == "CLK" || RTLIL::unescape_id(x) == "C")
|
||||||
|
i.item("clock", "true");
|
||||||
|
if (RTLIL::unescape_id(x) == "Q")
|
||||||
|
i.item("function", "IQ");
|
||||||
|
f << "\t\t}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
f << "\t\tff (\"IQ\",\"IQ_N\") {\n";
|
||||||
|
i.indent = 3;
|
||||||
|
// TODO polarities?
|
||||||
|
if (ffType.has_clk) {
|
||||||
|
auto pin = ffType.is_fine ? "C" : "CLK";
|
||||||
|
i.item("clocked_on", pin);
|
||||||
|
}
|
||||||
|
if (ffType.has_arst) {
|
||||||
|
auto meaning = (ffType.val_arst == State::S1) ? "preset" : "clear";
|
||||||
|
auto pin = ffType.is_fine ? "R" : "ARST";
|
||||||
|
i.item(meaning, pin);
|
||||||
|
}
|
||||||
|
auto next_state = ffType.has_ce ? "D & EN" : "D";
|
||||||
|
i.item("next_state", next_state);
|
||||||
|
f << "\t\t}\n";
|
||||||
|
|
||||||
|
|
||||||
|
// bool has_aload;
|
||||||
|
// bool has_srst;
|
||||||
|
// bool has_arst;
|
||||||
|
// bool has_sr;
|
||||||
|
f << "\t}\n";
|
||||||
|
}
|
||||||
void liberty_cell(Module* base, Module* derived, std::ostream& f)
|
void liberty_cell(Module* base, Module* derived, std::ostream& f)
|
||||||
{
|
{
|
||||||
auto base_name = base->name.str().substr(1);
|
auto base_name = base->name.str().substr(1);
|
||||||
|
@ -53,6 +131,10 @@ struct LibertyStubber {
|
||||||
log_debug("skip skeleton for %s\n", base_name.c_str());
|
log_debug("skip skeleton for %s\n", base_name.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RTLIL::builtin_ff_cell_types().count(base_name))
|
||||||
|
return liberty_flop(base, derived, f);
|
||||||
|
|
||||||
auto& base_type = ct.cell_types[base_name];
|
auto& base_type = ct.cell_types[base_name];
|
||||||
f << "\tcell (\"" << derived_name << "\") {\n";
|
f << "\tcell (\"" << derived_name << "\") {\n";
|
||||||
for (auto x : derived->ports) {
|
for (auto x : derived->ports) {
|
||||||
|
@ -73,7 +155,7 @@ struct LibertyStubber {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IcellLiberty : Pass {
|
struct IcellLiberty : Pass {
|
||||||
IcellLiberty() : Pass("icell_liberty", "derive box modules") {}
|
IcellLiberty() : Pass("icell_liberty", "write Liberty interfaces for used internal cells") {}
|
||||||
void help() override
|
void help() override
|
||||||
{
|
{
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue