aboutsummaryrefslogtreecommitdiffstats
path: root/docs/source/CHAPTER_Prog
diff options
context:
space:
mode:
Diffstat (limited to 'docs/source/CHAPTER_Prog')
-rw-r--r--docs/source/CHAPTER_Prog/.gitignore3
-rw-r--r--docs/source/CHAPTER_Prog/Makefile12
-rw-r--r--docs/source/CHAPTER_Prog/stubnets.cc130
-rw-r--r--docs/source/CHAPTER_Prog/test.v8
4 files changed, 153 insertions, 0 deletions
diff --git a/docs/source/CHAPTER_Prog/.gitignore b/docs/source/CHAPTER_Prog/.gitignore
new file mode 100644
index 000000000..fa83c3212
--- /dev/null
+++ b/docs/source/CHAPTER_Prog/.gitignore
@@ -0,0 +1,3 @@
+stubnets.so
+stubnets.d
+*.log
diff --git a/docs/source/CHAPTER_Prog/Makefile b/docs/source/CHAPTER_Prog/Makefile
new file mode 100644
index 000000000..8e326bdc2
--- /dev/null
+++ b/docs/source/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/docs/source/CHAPTER_Prog/stubnets.cc b/docs/source/CHAPTER_Prog/stubnets.cc
new file mode 100644
index 000000000..566d24b18
--- /dev/null
+++ b/docs/source/CHAPTER_Prog/stubnets.cc
@@ -0,0 +1,130 @@
+// 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/yosys.h"
+#include "kernel/sigtools.h"
+
+#include <string>
+#include <map>
+#include <set>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+// 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::SigBit, int> bit_usage_count;
+
+ // count output 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);
+
+ // add each bit to bit_usage_count, unless it is a constant
+ for (auto &bit : sig)
+ if (bit.wire != NULL)
+ bit_usage_count[bit]++;
+ }
+
+ // 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 separate bits
+ RTLIL::SigSpec sig = sigmap(wire);
+
+ // for each bit (unless it is a constant):
+ // check if it is used at least two times and add to stub_bits otherwise
+ for (int i = 0; i < GetSize(sig); i++)
+ if (sig[i].wire != NULL && (bit_usage_count[sig[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 (GetSize(stub_bits) == GetSize(sig)) {
+ 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") { }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ // variables to mirror information from passed options
+ bool report_bits = 0;
+
+ log_header(design, "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;
+
+PRIVATE_NAMESPACE_END
diff --git a/docs/source/CHAPTER_Prog/test.v b/docs/source/CHAPTER_Prog/test.v
new file mode 100644
index 000000000..201f75006
--- /dev/null
+++ b/docs/source/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
n381' href='#n381'>381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455