summaryrefslogtreecommitdiff
path: root/manual/CHAPTER_Prog
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-01-28 06:55:47 +0100
committerClifford Wolf <clifford@clifford.at>2014-01-28 06:55:47 +0100
commit2cb47355d4b3e8021a88f68f7a5f33ce46ff51b0 (patch)
tree83a3e52f3a46f2db264106798e416da63e7ae743 /manual/CHAPTER_Prog
parent842ca2f011a6030faccc690986accb0ca8035ec8 (diff)
Renamed manual/FILES_* directories
Diffstat (limited to 'manual/CHAPTER_Prog')
-rw-r--r--manual/CHAPTER_Prog/Makefile12
-rw-r--r--manual/CHAPTER_Prog/stubnets.cc133
-rw-r--r--manual/CHAPTER_Prog/test.v8
3 files changed, 153 insertions, 0 deletions
diff --git a/manual/CHAPTER_Prog/Makefile b/manual/CHAPTER_Prog/Makefile
new file mode 100644
index 00000000..8e326bdc
--- /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 00000000..1c71f78b
--- /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 00000000..201f7500
--- /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