Selection plugin: Add initial version of selection_to_tcl_list command Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/Makefile b/Makefile index fe3f92d..6818481 100644 --- a/Makefile +++ b/Makefile
@@ -1,4 +1,4 @@ -PLUGIN_LIST := fasm xdc params +PLUGIN_LIST := fasm xdc params selection PLUGINS := $(foreach plugin,$(PLUGIN_LIST),$(plugin).so) PLUGINS_INSTALL := $(foreach plugin,$(PLUGIN_LIST),install_$(plugin)) PLUGINS_CLEAN := $(foreach plugin,$(PLUGIN_LIST),clean_$(plugin))
diff --git a/selection-plugin/Makefile b/selection-plugin/Makefile new file mode 100644 index 0000000..6c6f96f --- /dev/null +++ b/selection-plugin/Makefile
@@ -0,0 +1,25 @@ +CXX = $(shell yosys-config --cxx) +CXXFLAGS = $(shell yosys-config --cxxflags) +LDFLAGS = $(shell yosys-config --ldflags) +LDLIBS = $(shell yosys-config --ldlibs) +PLUGINS_DIR = $(shell yosys-config --datdir)/plugins + +OBJS = selection.o + +selection.so: $(OBJS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) + +install_plugin: selection.so + mkdir -p $(PLUGINS_DIR) + cp $< $(PLUGINS_DIR)/$< + +test: + $(MAKE) -C tests all + +.PHONY: install +install: install_plugin + +clean: + rm -f *.d *.o *.so + $(MAKE) -C tests clean +
diff --git a/selection-plugin/selection.cc b/selection-plugin/selection.cc new file mode 100644 index 0000000..6f224ff --- /dev/null +++ b/selection-plugin/selection.cc
@@ -0,0 +1,91 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2020 The Symbiflow Authors + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "kernel/register.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" + +USING_YOSYS_NAMESPACE + +PRIVATE_NAMESPACE_BEGIN + + +struct SelectionToTclList : public Pass { + SelectionToTclList() : Pass("selection_to_tcl_list", "Extract selection to TCL list") {} + + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" selection_to_tcl_list selection\n"); + log("\n"); + log("Extract the current selection to a Tcl List with selection object names. \n"); + log("\n"); + } + + void AddObjectNameToTclList(RTLIL::IdString& module, RTLIL::IdString& object, Tcl_Obj* tcl_list) { + std::string name = RTLIL::unescape_id(module) + "/" + RTLIL::unescape_id(object); + Tcl_Obj* value_obj = Tcl_NewStringObj(name.c_str(), name.size()); + Tcl_ListObjAppendElement(yosys_get_tcl_interp(), tcl_list, value_obj); + } + + void execute(std::vector<std::string> args, RTLIL::Design* design) override + { + if (args.size() == 1) { + log_error("Incorrect number of arguments"); + } + extra_args(args, 1, design); + + Tcl_Interp *interp = yosys_get_tcl_interp(); + Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL); + + auto& selection = design->selection(); + if (selection.empty()) { + log_warning("Selection is empty\n"); + } + + for (auto mod : design->modules()) { + if (selection.selected_module(mod->name)) { + for (auto wire : mod->wires()) { + if (selection.selected_member(mod->name, wire->name)) { + AddObjectNameToTclList(mod->name, wire->name, tcl_list); + } + } + for (auto &it : mod->memories) { + if (selection.selected_member(mod->name, it.first)) { + AddObjectNameToTclList(mod->name, it.first, tcl_list); + } + } + for (auto cell : mod->cells()) { + if (selection.selected_member(mod->name, cell->name)) { + AddObjectNameToTclList(mod->name, cell->name, tcl_list); + } + } + for (auto &it : mod->processes) { + if (selection.selected_member(mod->name, it.first)) { + AddObjectNameToTclList(mod->name, it.first, tcl_list); + } + } + } + } + Tcl_SetObjResult(interp, tcl_list); + } + +} SelectionToTclList; + +PRIVATE_NAMESPACE_END
diff --git a/selection-plugin/tests/Makefile b/selection-plugin/tests/Makefile new file mode 100644 index 0000000..e29a406 --- /dev/null +++ b/selection-plugin/tests/Makefile
@@ -0,0 +1,32 @@ +TESTS = counter +.PHONY: $(TESTS) + +counter_verify = $(call compare,counter,txt) + +all: $(TESTS) +compare = diff $(1)/$(1).golden.$(2) $(1)/$(1).$(2) + +define test_tpl = +$(1): $(1)/$(1).txt + $$($(1)_verify) + RETVAL=$$$$? ; \ + if [ $$$$RETVAL -eq 0 ]; then \ + echo "$(1) PASS"; \ + true; \ + else \ + echo "$(1) FAIL"; \ + false; \ + fi + +$(1)/$(1).txt: $(1)/$(1).v + cd $(1); \ + INPUT_SDC_FILE=$(1).input.sdc \ + OUTPUT_SDC_FILE=$(1).sdc \ + yosys -p "tcl $(1).tcl" -l yosys.log + +endef + +$(foreach test,$(TESTS),$(eval $(call test_tpl,$(test)))) + +clean: + rm -rf $(foreach test,$(TESTS),$(test)/$(test).sdc $(test)/$(test).txt $(test)/yosys.log)
diff --git a/selection-plugin/tests/counter/counter.golden.txt b/selection-plugin/tests/counter/counter.golden.txt new file mode 100644 index 0000000..aee0a91 --- /dev/null +++ b/selection-plugin/tests/counter/counter.golden.txt
@@ -0,0 +1 @@ +{middle/$1\cnt[1:0]} {middle/$add$counter.v:32$5_Y} {middle/$0\cnt[1:0]} middle/clk_int middle/cnt middle/out middle/clk {top/$1\cnt[1:0]} {top/$add$counter.v:14$2_Y} {top/$0\cnt[1:0]} top/ibuf_out top/ibuf_proxy_out top/clk_int_2 top/clk_int_1 top/cnt top/out top/in top/clk2 top/clk
diff --git a/selection-plugin/tests/counter/counter.tcl b/selection-plugin/tests/counter/counter.tcl new file mode 100644 index 0000000..aa5a524 --- /dev/null +++ b/selection-plugin/tests/counter/counter.tcl
@@ -0,0 +1,18 @@ +yosys -import +plugin -i selection + +# Import the commands from the plugins to the tcl interpreter +yosys -import + +read_verilog counter.v +read_verilog -specify -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v +read_verilog -lib +/xilinx/cells_xtra.v +hierarchy -check -auto-top + +puts "List: [selection_to_tcl_list w:*]" + +# Write the selection to file +set fh [open counter.txt w] +set selection_list [selection_to_tcl_list w:*] +puts $fh $selection_list +close $fh
diff --git a/selection-plugin/tests/counter/counter.v b/selection-plugin/tests/counter/counter.v new file mode 100644 index 0000000..564fae5 --- /dev/null +++ b/selection-plugin/tests/counter/counter.v
@@ -0,0 +1,36 @@ +module top(input clk, + input clk2, + input [1:0] in, + output [5:0] out ); + +reg [1:0] cnt = 0; +wire clk_int_1, clk_int_2; +IBUF ibuf_proxy(.I(clk), .O(ibuf_proxy_out)); +IBUF ibuf_inst(.I(ibuf_proxy_out), .O(ibuf_out)); +assign clk_int_1 = ibuf_out; +assign clk_int_2 = clk_int_1; + +always @(posedge clk_int_2) begin + cnt <= cnt + 1; +end + +middle middle_inst_1(.clk(ibuf_out), .out(out[2])); +middle middle_inst_2(.clk(clk_int_1), .out(out[3])); +middle middle_inst_3(.clk(clk_int_2), .out(out[4])); +middle middle_inst_4(.clk(clk2), .out(out[5])); + +assign out[1:0] = {cnt[0], in[0]}; +endmodule + +module middle(input clk, + output out); + +reg [1:0] cnt = 0; +wire clk_int; +assign clk_int = clk; +always @(posedge clk_int) begin + cnt <= cnt + 1; +end + +assign out = cnt[0]; +endmodule