mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-14 09:56:16 +00:00
Fix comments and add freq annotation in sim pass
This commit is contained in:
parent
fcfa2fff31
commit
c2aa611e5d
2 changed files with 33 additions and 40 deletions
|
@ -5,20 +5,12 @@
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
int sigIsConstant(RTLIL::SigSpec sig)
|
// Recursively traverses backward from a sig, record if a cell was traversed, and push onto the cell's inputs.
|
||||||
{
|
// Similarly with assign statements traverses lhs -> rhs
|
||||||
if (sig.is_chunk()) {
|
|
||||||
if ((sig.as_chunk()).wire == NULL) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void recordTransFanin(RTLIL::SigSpec &sig, dict<RTLIL::SigSpec, std::set<Cell *> *> &sig2CellsInFanin,
|
void recordTransFanin(RTLIL::SigSpec &sig, dict<RTLIL::SigSpec, std::set<Cell *> *> &sig2CellsInFanin,
|
||||||
dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig2RhsSig, std::set<Cell *> &visitedCells, std::set<RTLIL::SigSpec> &visitedSigSpec)
|
dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig2RhsSig, std::set<Cell *> &visitedCells, std::set<RTLIL::SigSpec> &visitedSigSpec)
|
||||||
{
|
{
|
||||||
if (sigIsConstant(sig)) {
|
if (sig.is_fully_const()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (visitedSigSpec.count(sig)) {
|
if (visitedSigSpec.count(sig)) {
|
||||||
|
@ -43,7 +35,6 @@ void recordTransFanin(RTLIL::SigSpec &sig, dict<RTLIL::SigSpec, std::set<Cell *>
|
||||||
RTLIL::SigSpec sub_actual = *it;
|
RTLIL::SigSpec sub_actual = *it;
|
||||||
recordTransFanin(sub_actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec);
|
recordTransFanin(sub_actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
recordTransFanin(actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec);
|
recordTransFanin(actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +48,7 @@ void recordTransFanin(RTLIL::SigSpec &sig, dict<RTLIL::SigSpec, std::set<Cell *>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signal cell driver(s)
|
// Signal cell driver(s), precompute a cell output signal to a cell map
|
||||||
void sigCellDrivers(RTLIL::Design *design, dict<RTLIL::SigSpec, std::set<Cell *> *> &sig2CellsInFanin)
|
void sigCellDrivers(RTLIL::Design *design, dict<RTLIL::SigSpec, std::set<Cell *> *> &sig2CellsInFanin)
|
||||||
{
|
{
|
||||||
for (auto cell : design->top_module()->cells()) {
|
for (auto cell : design->top_module()->cells()) {
|
||||||
|
@ -91,13 +82,13 @@ void sigCellDrivers(RTLIL::Design *design, dict<RTLIL::SigSpec, std::set<Cell *>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign statements fanin
|
// Assign statements fanin, traces the lhs to rhs sigspecs and precompute a map
|
||||||
void lhs2rhs(RTLIL::Design *design, dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig2rhsSig)
|
void lhs2rhs(RTLIL::Design *design, dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig2rhsSig)
|
||||||
{
|
{
|
||||||
for (auto it = design->top_module()->connections().begin(); it != design->top_module()->connections().end(); ++it) {
|
for (auto it = design->top_module()->connections().begin(); it != design->top_module()->connections().end(); ++it) {
|
||||||
RTLIL::SigSpec lhs = it->first;
|
RTLIL::SigSpec lhs = it->first;
|
||||||
RTLIL::SigSpec rhs = it->second;
|
RTLIL::SigSpec rhs = it->second;
|
||||||
if (sigIsConstant(rhs)) {
|
if (rhs.is_fully_const()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!lhs.is_chunk()) {
|
if (!lhs.is_chunk()) {
|
||||||
|
@ -106,7 +97,7 @@ void lhs2rhs(RTLIL::Design *design, dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig
|
||||||
long unsigned rhsSize = 0;
|
long unsigned rhsSize = 0;
|
||||||
while (rit != rhs.chunks().rend()) {
|
while (rit != rhs.chunks().rend()) {
|
||||||
RTLIL::SigSpec sub_rhs = *rit;
|
RTLIL::SigSpec sub_rhs = *rit;
|
||||||
if (sigIsConstant(sub_rhs)) {
|
if (sub_rhs.is_fully_const()) {
|
||||||
rhsSize += (sub_rhs.as_chunk()).width;
|
rhsSize += (sub_rhs.as_chunk()).width;
|
||||||
} else {
|
} else {
|
||||||
rhsSize++;
|
rhsSize++;
|
||||||
|
@ -122,7 +113,7 @@ void lhs2rhs(RTLIL::Design *design, dict<RTLIL::SigSpec, RTLIL::SigSpec> &lhsSig
|
||||||
while (rit != rhs.chunks().rend()) {
|
while (rit != rhs.chunks().rend()) {
|
||||||
RTLIL::SigSpec sub_lhs = *lit;
|
RTLIL::SigSpec sub_lhs = *lit;
|
||||||
RTLIL::SigSpec sub_rhs = *rit;
|
RTLIL::SigSpec sub_rhs = *rit;
|
||||||
if (sigIsConstant(sub_rhs)) {
|
if (sub_rhs.is_fully_const()) {
|
||||||
int constSize = (sub_rhs.as_chunk()).width;
|
int constSize = (sub_rhs.as_chunk()).width;
|
||||||
while (constSize--) {
|
while (constSize--) {
|
||||||
lit++;
|
lit++;
|
||||||
|
@ -167,7 +158,11 @@ std::string replaceAll(std::string_view str, std::string_view from, std::string_
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SplitNetlist : public ScriptPass {
|
struct SplitNetlist : public ScriptPass {
|
||||||
SplitNetlist() : ScriptPass("splitnetlist", "Splits a netlist into multiple modules using transitive fanin grouping") {}
|
SplitNetlist()
|
||||||
|
: ScriptPass("splitnetlist", "Splits a netlist into multiple modules using transitive fanin grouping. \
|
||||||
|
The output names that belong in the same logical cluster have to have the same prefix: <prefix>_<name>")
|
||||||
|
{
|
||||||
|
}
|
||||||
void script() {}
|
void script() {}
|
||||||
|
|
||||||
void execute(std::vector<std::string>, RTLIL::Design *design) override
|
void execute(std::vector<std::string>, RTLIL::Design *design) override
|
||||||
|
@ -176,16 +171,21 @@ struct SplitNetlist : public ScriptPass {
|
||||||
log_error("No design object");
|
log_error("No design object");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Precompute cell output sigspec to cell map
|
||||||
dict<RTLIL::SigSpec, std::set<Cell *> *> sig2CellsInFanin;
|
dict<RTLIL::SigSpec, std::set<Cell *> *> sig2CellsInFanin;
|
||||||
sigCellDrivers(design, sig2CellsInFanin);
|
sigCellDrivers(design, sig2CellsInFanin);
|
||||||
|
// Precompute lhs to rhs sigspec map
|
||||||
dict<RTLIL::SigSpec, RTLIL::SigSpec> lhsSig2RhsSig;
|
dict<RTLIL::SigSpec, RTLIL::SigSpec> lhsSig2RhsSig;
|
||||||
lhs2rhs(design, lhsSig2RhsSig);
|
lhs2rhs(design, lhsSig2RhsSig);
|
||||||
|
// Struct representing a cluster
|
||||||
typedef struct CellsAndSigs {
|
typedef struct CellsAndSigs {
|
||||||
std::set<Cell *> visitedCells;
|
std::set<Cell *> visitedCells;
|
||||||
std::set<RTLIL::SigSpec> visitedSigSpec;
|
std::set<RTLIL::SigSpec> visitedSigSpec;
|
||||||
} CellsAndSigs;
|
} CellsAndSigs;
|
||||||
|
// Cluster mapped by prefix
|
||||||
typedef std::map<std::string, CellsAndSigs> CellName_ObjectMap;
|
typedef std::map<std::string, CellsAndSigs> CellName_ObjectMap;
|
||||||
CellName_ObjectMap cellName_ObjectMap;
|
CellName_ObjectMap cellName_ObjectMap;
|
||||||
|
// Record logic cone by output sharing the same prefix
|
||||||
for (auto wire : design->top_module()->wires()) {
|
for (auto wire : design->top_module()->wires()) {
|
||||||
if (!wire->port_output)
|
if (!wire->port_output)
|
||||||
continue;
|
continue;
|
||||||
|
@ -194,12 +194,14 @@ struct SplitNetlist : public ScriptPass {
|
||||||
std::set<Cell *> visitedCells;
|
std::set<Cell *> visitedCells;
|
||||||
std::set<RTLIL::SigSpec> visitedSigSpec;
|
std::set<RTLIL::SigSpec> visitedSigSpec;
|
||||||
RTLIL::SigSpec actual = wire;
|
RTLIL::SigSpec actual = wire;
|
||||||
|
// Visit the output sigspec
|
||||||
recordTransFanin(actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec);
|
recordTransFanin(actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec);
|
||||||
|
// Visit the output sigspec bits
|
||||||
for (int i = 0; i < actual.size(); i++) {
|
for (int i = 0; i < actual.size(); i++) {
|
||||||
SigSpec bit_sig = actual.extract(i, 1);
|
SigSpec bit_sig = actual.extract(i, 1);
|
||||||
recordTransFanin(bit_sig, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec);
|
recordTransFanin(bit_sig, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec);
|
||||||
}
|
}
|
||||||
|
// Record the visited objects in the corresponding cluster
|
||||||
CellName_ObjectMap::iterator itr = cellName_ObjectMap.find(std::string(po_prefix));
|
CellName_ObjectMap::iterator itr = cellName_ObjectMap.find(std::string(po_prefix));
|
||||||
if (itr == cellName_ObjectMap.end()) {
|
if (itr == cellName_ObjectMap.end()) {
|
||||||
CellsAndSigs components;
|
CellsAndSigs components;
|
||||||
|
@ -211,7 +213,7 @@ struct SplitNetlist : public ScriptPass {
|
||||||
}
|
}
|
||||||
cellName_ObjectMap.emplace(std::string(po_prefix), components);
|
cellName_ObjectMap.emplace(std::string(po_prefix), components);
|
||||||
} else {
|
} else {
|
||||||
CellsAndSigs &components = (*itr).second;
|
CellsAndSigs &components = itr->second;
|
||||||
for (auto cell : visitedCells) {
|
for (auto cell : visitedCells) {
|
||||||
components.visitedCells.insert(cell);
|
components.visitedCells.insert(cell);
|
||||||
}
|
}
|
||||||
|
@ -220,31 +222,21 @@ struct SplitNetlist : public ScriptPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Create submod attributes for the submod command
|
||||||
for (CellName_ObjectMap::iterator itr = cellName_ObjectMap.begin(); itr != cellName_ObjectMap.end(); itr++) {
|
for (CellName_ObjectMap::iterator itr = cellName_ObjectMap.begin(); itr != cellName_ObjectMap.end(); itr++) {
|
||||||
// std::cout << "Cluster name: " << (*itr).first << std::endl;
|
// std::cout << "Cluster name: " << itr->first << std::endl;
|
||||||
CellsAndSigs &components = (*itr).second;
|
CellsAndSigs &components = itr->second;
|
||||||
for (auto cell : components.visitedCells) {
|
for (auto cell : components.visitedCells) {
|
||||||
cell->set_string_attribute(RTLIL::escape_id("submod"), (*itr).first);
|
cell->set_string_attribute(RTLIL::escape_id("submod"), itr->first);
|
||||||
// std::cout << " CELL: " << cell->name.c_str() << std::endl;
|
// std::cout << " CELL: " << cell->name.c_str() << std::endl;
|
||||||
}
|
}
|
||||||
//for (auto sigspec : components.visitedSigSpec) {
|
// for (auto sigspec : components.visitedSigSpec) {
|
||||||
// std::cout << " SIG: " << SigName(sigspec) << std::endl;
|
// std::cout << " SIG: " << SigName(sigspec) << std::endl;
|
||||||
//}
|
// }
|
||||||
// std::cout << std::endl;
|
// std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
// Execute the submod command
|
||||||
Pass::call(design, "submod -copy -noclean");
|
Pass::call(design, "submod -copy -noclean");
|
||||||
// Rename all the modules
|
|
||||||
std::set<Module *> modules;
|
|
||||||
for (Module *module : design->modules()) {
|
|
||||||
modules.insert(module);
|
|
||||||
}
|
|
||||||
std::string topmodule_name = id2String(design->top_module()->name);
|
|
||||||
for (Module *module : modules) {
|
|
||||||
std::string name = id2String(module->name);
|
|
||||||
name = replaceAll(name, "\\" + topmodule_name + "_\\fast_", "\\");
|
|
||||||
name = replaceAll(name, "\\" + topmodule_name + "_\\slow_", "\\");
|
|
||||||
design->rename(module, name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} SplitNetlist;
|
} SplitNetlist;
|
||||||
|
|
||||||
|
|
|
@ -2355,8 +2355,7 @@ struct VCDWriter : public OutputWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!worker->timescale.empty())
|
if (!worker->timescale.empty())
|
||||||
vcdfile << stringf("$timescale %s $end\n", worker->timescale.c_str());
|
vcdfile << stringf("$timescale 1%s $end\n", worker->timescale.c_str());
|
||||||
|
|
||||||
worker->top->write_output_header(
|
worker->top->write_output_header(
|
||||||
[this](IdString name) { vcdfile << stringf("$scope module %s $end\n", log_id(name)); },
|
[this](IdString name) { vcdfile << stringf("$scope module %s $end\n", log_id(name)); },
|
||||||
[this]() { vcdfile << stringf("$upscope $end\n");},
|
[this]() { vcdfile << stringf("$upscope $end\n");},
|
||||||
|
@ -2500,6 +2499,8 @@ struct AnnotateActivity : public OutputWriter {
|
||||||
SignalActivityDataMap::iterator itr = dataMap.find(clk);
|
SignalActivityDataMap::iterator itr = dataMap.find(clk);
|
||||||
std::vector<uint32_t> &clktoggleCounts = itr->second.toggleCounts;
|
std::vector<uint32_t> &clktoggleCounts = itr->second.toggleCounts;
|
||||||
double clk_period = real_timescale * (double)max_time / (clktoggleCounts[0] / 2);
|
double clk_period = real_timescale * (double)max_time / (clktoggleCounts[0] / 2);
|
||||||
|
double frequency = 1 / clk_period;
|
||||||
|
worker->top->module->set_string_attribute("$FREQUENCY", std::to_string(frequency));
|
||||||
if (debug) {
|
if (debug) {
|
||||||
std::cout << "Clock toggle count: " << clktoggleCounts[0] << "\n";
|
std::cout << "Clock toggle count: " << clktoggleCounts[0] << "\n";
|
||||||
std::cout << "Max time: " << max_time << "\n";
|
std::cout << "Max time: " << max_time << "\n";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue