diff options
Diffstat (limited to 'manual/CHAPTER_Prog')
-rw-r--r-- | manual/CHAPTER_Prog/Makefile | 12 | ||||
-rw-r--r-- | manual/CHAPTER_Prog/stubnets.cc | 133 | ||||
-rw-r--r-- | manual/CHAPTER_Prog/test.v | 8 |
3 files changed, 153 insertions, 0 deletions
diff --git a/manual/CHAPTER_Prog/Makefile b/manual/CHAPTER_Prog/Makefile new file mode 100644 index 000000000..8e326bdc2 --- /dev/null +++ b/manual/CHAPTER_Prog/Makefile @@ -0,0 +1,12 @@ +test: stubnets.so + yosys -ql test1.log -m ./stubnets.so test.v -p "stubnets" + yosys -ql test2.log -m ./stubnets.so test.v -p "opt; stubnets" + yosys -ql test3.log -m ./stubnets.so test.v -p "techmap; opt; stubnets -report_bits" + tail test1.log test2.log test3.log + +stubnets.so: stubnets.cc + yosys-config --exec --cxx --cxxflags --ldflags -o $@ -shared $^ --ldlibs + +clean: + rm -f test1.log test2.log test3.log + rm -f stubnets.so stubnets.d diff --git a/manual/CHAPTER_Prog/stubnets.cc b/manual/CHAPTER_Prog/stubnets.cc new file mode 100644 index 000000000..1c71f78b8 --- /dev/null +++ b/manual/CHAPTER_Prog/stubnets.cc @@ -0,0 +1,133 @@ +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +#include "kernel/rtlil.h" +#include "kernel/register.h" +#include "kernel/sigtools.h" +#include "kernel/log.h" + +#include <string> +#include <map> +#include <set> + +// this function is called for each module in the design +static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool report_bits) +{ + // use a SigMap to convert nets to a unique representation + SigMap sigmap(module); + + // count how many times a single-bit signal is used + std::map<RTLIL::SigSpec, int> bit_usage_count; + + // count ouput lines for this module (needed only for summary output at the end) + int line_count = 0; + + log("Looking for stub wires in module %s:\n", RTLIL::id2cstr(module->name)); + + // For all ports on all cells + for (auto &cell_iter : module->cells) + for (auto &conn : cell_iter.second->connections) + { + // Get the signals on the port + // (use sigmap to get a uniqe signal name) + RTLIL::SigSpec sig = sigmap(conn.second); + + // split the signal up into single-bit chunks + sig.expand(); + + // add each chunk to bit_usage_count, unless it is a constant + for (auto &c : sig.chunks) + if (c.wire != NULL) + bit_usage_count[c]++; + } + + // for each wire in the module + for (auto &wire_iter : module->wires) + { + RTLIL::Wire *wire = wire_iter.second; + + // .. but only selected wires + if (!design->selected(module, wire)) + continue; + + // add +1 usage if this wire actually is a port + int usage_offset = wire->port_id > 0 ? 1 : 0; + + // we will record which bits of the (possibly multi-bit) wire are stub signals + std::set<int> stub_bits; + + // get a signal description for this wire and split it into seperate bits + RTLIL::SigSpec sig = sigmap(wire); + sig.expand(); + + // for each bit (unless it is a constant): + // check if it is used at least two times and add to stub_bits otherwise + for (size_t i = 0; i < sig.chunks.size(); i++) + if (sig.chunks[i].wire != NULL && (bit_usage_count[sig.chunks[i]] + + usage_offset) < 2) + stub_bits.insert(i); + + // continue if no stub bits found + if (stub_bits.size() == 0) + continue; + + // report stub bits and/or stub wires, don't report single bits + // if called with report_bits set to false. + if (int(stub_bits.size()) == sig.width) { + log(" found stub wire: %s\n", RTLIL::id2cstr(wire->name)); + } else { + if (!report_bits) + continue; + log(" found wire with stub bits: %s [", RTLIL::id2cstr(wire->name)); + for (int bit : stub_bits) + log("%s%d", bit == *stub_bits.begin() ? "" : ", ", bit); + log("]\n"); + } + + // we have outputted a line, increment summary counter + line_count++; + } + + // report summary + if (report_bits) + log(" found %d stub wires or wires with stub bits.\n", line_count); + else + log(" found %d stub wires.\n", line_count); +} + +// each pass contains a singleton object that is derived from Pass +struct StubnetsPass : public Pass { + StubnetsPass() : Pass("stubnets") { } + virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + { + // variables to mirror information from passed options + bool report_bits = 0; + + log_header("Executing STUBNETS pass (find stub nets).\n"); + + // parse options + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-report_bits") { + report_bits = true; + continue; + } + break; + } + + // handle extra options (e.g. selection) + extra_args(args, argidx, design); + + // call find_stub_nets() for each module that is either + // selected as a whole or contains selected objects. + for (auto &it : design->modules) + if (design->selected_module(it.first)) + find_stub_nets(design, it.second, report_bits); + } +} StubnetsPass; + diff --git a/manual/CHAPTER_Prog/test.v b/manual/CHAPTER_Prog/test.v new file mode 100644 index 000000000..201f75006 --- /dev/null +++ b/manual/CHAPTER_Prog/test.v @@ -0,0 +1,8 @@ +module uut(in1, in2, in3, out1, out2); + +input [8:0] in1, in2, in3; +output [8:0] out1, out2; + +assign out1 = in1 + in2 + (in3 >> 4); + +endmodule |