mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
311396860b
2
Makefile
2
Makefile
|
@ -357,7 +357,7 @@ endif
|
|||
endif
|
||||
|
||||
ifeq ($(ENABLE_VERIFIC),1)
|
||||
VERIFIC_DIR ?= /usr/local/src/verific_lib_eval
|
||||
VERIFIC_DIR ?= /usr/local/src/verific_lib
|
||||
VERIFIC_COMPONENTS ?= verilog vhdl database util containers hier_tree
|
||||
CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABLE_VERIFIC
|
||||
ifeq ($(OS), Darwin)
|
||||
|
|
18
README.md
18
README.md
|
@ -117,7 +117,7 @@ reading the design using the Verilog frontend:
|
|||
|
||||
yosys> read_verilog tests/simple/fiedler-cooley.v
|
||||
|
||||
writing the design to the console in yosys's internal format:
|
||||
writing the design to the console in Yosys's internal format:
|
||||
|
||||
yosys> write_ilang
|
||||
|
||||
|
@ -234,7 +234,7 @@ Unsupported Verilog-2005 Features
|
|||
=================================
|
||||
|
||||
The following Verilog-2005 features are not supported by
|
||||
yosys and there are currently no plans to add support
|
||||
Yosys and there are currently no plans to add support
|
||||
for them:
|
||||
|
||||
- Non-synthesizable language features as defined in
|
||||
|
@ -285,9 +285,9 @@ Verilog Attributes and non-standard features
|
|||
storage element. The register itself will always have all bits set
|
||||
to 'x' (undefined). The variable may only be used as blocking assigned
|
||||
temporary variable within an always block. This is mostly used internally
|
||||
by yosys to synthesize Verilog functions and access arrays.
|
||||
by Yosys to synthesize Verilog functions and access arrays.
|
||||
|
||||
- The ``onehot`` attribute on wires mark them as onehot state register. This
|
||||
- The ``onehot`` attribute on wires mark them as one-hot state register. This
|
||||
is used for example for memory port sharing and set by the fsm_map pass.
|
||||
|
||||
- The ``blackbox`` attribute on modules is used to mark empty stub modules
|
||||
|
@ -319,13 +319,13 @@ Verilog Attributes and non-standard features
|
|||
through the synthesis. When entities are combined, a new |-separated
|
||||
string is created that contains all the string from the original entities.
|
||||
|
||||
- In addition to the ``(* ... *)`` attribute syntax, yosys supports
|
||||
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
|
||||
the non-standard ``{* ... *}`` attribute syntax to set default attributes
|
||||
for everything that comes after the ``{* ... *}`` statement. (Reset
|
||||
by adding an empty ``{* *}`` statement.)
|
||||
|
||||
- In module parameter and port declarations, and cell port and parameter
|
||||
lists, a trailing comma is ignored. This simplifies writing verilog code
|
||||
lists, a trailing comma is ignored. This simplifies writing Verilog code
|
||||
generators a bit in some cases.
|
||||
|
||||
- Modules can be declared with ``module mod_name(...);`` (with three dots
|
||||
|
@ -410,11 +410,11 @@ Non-standard or SystemVerilog features for formal verification
|
|||
|
||||
- The system functions ``$allconst`` and ``$allseq`` can be used to construct
|
||||
formal exist-forall problems. Assumptions only hold if the trace satisfies
|
||||
the assumtion for all ``$allconst/$allseq`` values. For assertions and cover
|
||||
the assumption for all ``$allconst/$allseq`` values. For assertions and cover
|
||||
statements it is sufficient if just one ``$allconst/$allseq`` value triggers
|
||||
the property (similar to ``$anyconst/$anyseq``).
|
||||
|
||||
- Wires/registers decalred using the ``anyconst/anyseq/allconst/allseq`` attribute
|
||||
- Wires/registers declared using the ``anyconst/anyseq/allconst/allseq`` attribute
|
||||
(for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if driven
|
||||
by a ``$anyconst/$anyseq/$allconst/$allseq`` function.
|
||||
|
||||
|
@ -485,6 +485,6 @@ Then execute, from the root of the repository:
|
|||
|
||||
Notes:
|
||||
|
||||
- To run `make manual` you need to have installed yosys with `make install`,
|
||||
- To run `make manual` you need to have installed Yosys with `make install`,
|
||||
otherwise it will fail on finding `kernel/yosys.h` while building
|
||||
`PRESENTATION_Prog`.
|
||||
|
|
|
@ -134,7 +134,7 @@ struct BtorWorker
|
|||
btorf_push(log_id(cell));
|
||||
|
||||
if (cell->type.in("$add", "$sub", "$mul", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx",
|
||||
"$concat", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_"))
|
||||
"$concat", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_"))
|
||||
{
|
||||
string btor_op;
|
||||
if (cell->type == "$add") btor_op = "add";
|
||||
|
|
|
@ -106,6 +106,10 @@ struct EdifBackend : public Backend {
|
|||
log(" if the design contains constant nets. use \"hilomap\" to map to custom\n");
|
||||
log(" constant drivers first)\n");
|
||||
log("\n");
|
||||
log(" -gndvccy\n");
|
||||
log(" create \"GND\" and \"VCC\" cells with \"Y\" outputs. (the default is \"G\"\n");
|
||||
log(" for \"GND\" and \"P\" for \"VCC\".)\n");
|
||||
log("\n");
|
||||
log(" -attrprop\n");
|
||||
log(" create EDIF properties for cell attributes\n");
|
||||
log("\n");
|
||||
|
@ -126,7 +130,7 @@ struct EdifBackend : public Backend {
|
|||
bool port_rename = false;
|
||||
bool attr_properties = false;
|
||||
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
||||
bool nogndvcc = false;
|
||||
bool nogndvcc = false, gndvccy = true;
|
||||
CellTypes ct(design);
|
||||
EdifNames edif_names;
|
||||
|
||||
|
@ -141,6 +145,10 @@ struct EdifBackend : public Backend {
|
|||
nogndvcc = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-gndvccy") {
|
||||
gndvccy = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-attrprop") {
|
||||
attr_properties = true;
|
||||
continue;
|
||||
|
@ -211,7 +219,7 @@ struct EdifBackend : public Backend {
|
|||
*f << stringf(" (cellType GENERIC)\n");
|
||||
*f << stringf(" (view VIEW_NETLIST\n");
|
||||
*f << stringf(" (viewType NETLIST)\n");
|
||||
*f << stringf(" (interface (port G (direction OUTPUT)))\n");
|
||||
*f << stringf(" (interface (port %c (direction OUTPUT)))\n", gndvccy ? 'Y' : 'G');
|
||||
*f << stringf(" )\n");
|
||||
*f << stringf(" )\n");
|
||||
|
||||
|
@ -219,7 +227,7 @@ struct EdifBackend : public Backend {
|
|||
*f << stringf(" (cellType GENERIC)\n");
|
||||
*f << stringf(" (view VIEW_NETLIST\n");
|
||||
*f << stringf(" (viewType NETLIST)\n");
|
||||
*f << stringf(" (interface (port P (direction OUTPUT)))\n");
|
||||
*f << stringf(" (interface (port %c (direction OUTPUT)))\n", gndvccy ? 'Y' : 'P');
|
||||
*f << stringf(" )\n");
|
||||
*f << stringf(" )\n");
|
||||
}
|
||||
|
@ -420,9 +428,9 @@ struct EdifBackend : public Backend {
|
|||
if (nogndvcc)
|
||||
log_error("Design contains constant nodes (map with \"hilomap\" first).\n");
|
||||
if (sig == RTLIL::State::S0)
|
||||
*f << stringf(" (portRef G (instanceRef GND))\n");
|
||||
*f << stringf(" (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G');
|
||||
if (sig == RTLIL::State::S1)
|
||||
*f << stringf(" (portRef P (instanceRef VCC))\n");
|
||||
*f << stringf(" (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P');
|
||||
}
|
||||
*f << stringf(" ))\n");
|
||||
}
|
||||
|
|
|
@ -748,7 +748,7 @@ struct SimplecBackend : public Backend {
|
|||
log("\n");
|
||||
log(" write_simplec [options] [filename]\n");
|
||||
log("\n");
|
||||
log("Write simple C code for simulating the design. The C code writen can be used to\n");
|
||||
log("Write simple C code for simulating the design. The C code written can be used to\n");
|
||||
log("simulate the design in a C environment, but the purpose of this command is to\n");
|
||||
log("generate code that works well with C-based formal verification.\n");
|
||||
log("\n");
|
||||
|
|
|
@ -3,12 +3,12 @@ module test(input [31:0] a, b, c, output [31:0] x, y, z, w);
|
|||
unit_y unit_y_inst (.a(a), .b(b), .c(c), .y(y));
|
||||
assign z = a ^ b ^ c, w = z;
|
||||
endmodule
|
||||
|
||||
|
||||
module unit_x(input [31:0] a, b, c, output [31:0] x);
|
||||
assign x = (a & b) | c;
|
||||
endmodule
|
||||
|
||||
|
||||
module unit_y(input [31:0] a, b, c, output [31:0] y);
|
||||
assign y = a & (b | c);
|
||||
endmodule
|
||||
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ yosys-smtbmc [options] <yosys_smt2_output>
|
|||
|
||||
--aig <aim_filename>:<aiw_filename>
|
||||
like above, but for map files and witness files that do not
|
||||
share a filename prefix (or use differen file extensions).
|
||||
share a filename prefix (or use different file extensions).
|
||||
|
||||
--aig-noheader
|
||||
the AIGER witness file does not include the status and
|
||||
|
@ -103,8 +103,8 @@ yosys-smtbmc [options] <yosys_smt2_output>
|
|||
--presat
|
||||
check if the design with assumptions but without assertions
|
||||
is SAT before checking if assertions are UNSAT. This will
|
||||
detect if there are contradicting assumtions. In some cases
|
||||
this will also help to "warmup" the solver, potentially
|
||||
detect if there are contradicting assumptions. In some cases
|
||||
this will also help to "warm up" the solver, potentially
|
||||
yielding a speedup.
|
||||
|
||||
--final-only
|
||||
|
@ -149,7 +149,7 @@ yosys-smtbmc [options] <yosys_smt2_output>
|
|||
--append <num_steps>
|
||||
add <num_steps> time steps at the end of the trace
|
||||
when creating a counter example (this additional time
|
||||
steps will still be constrained by assumtions)
|
||||
steps will still be constrained by assumptions)
|
||||
""" + so.helpmsg())
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
@ -784,7 +784,7 @@ class SmtIo:
|
|||
|
||||
def get_path(self, mod, path):
|
||||
assert mod in self.modinfo
|
||||
path = path.split(".")
|
||||
path = path.replace("\\", "/").split(".")
|
||||
|
||||
for i in range(len(path)-1):
|
||||
first = ".".join(path[0:i+1])
|
||||
|
|
|
@ -109,7 +109,7 @@ struct TableBackend : public Backend {
|
|||
else if (cell->output(conn.first))
|
||||
*f << "out" << "\t";
|
||||
else
|
||||
*f << "unkown" << "\t";
|
||||
*f << "unknown" << "\t";
|
||||
|
||||
*f << log_signal(sigmap(conn.second)) << "\n";
|
||||
}
|
||||
|
|
|
@ -126,6 +126,33 @@ std::string id(RTLIL::IdString internal_id, bool may_rename = true)
|
|||
break;
|
||||
}
|
||||
|
||||
const pool<string> keywords = {
|
||||
// IEEE 1800-2017 Annex B
|
||||
"accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before",
|
||||
"begin", "bind", "bins", "binsof", "bit", "break", "buf", "bufif0", "bufif1", "byte", "case", "casex", "casez", "cell", "chandle",
|
||||
"checker", "class", "clocking", "cmos", "config", "const", "constraint", "context", "continue", "cover", "covergroup", "coverpoint",
|
||||
"cross", "deassign", "default", "defparam", "design", "disable", "dist", "do", "edge", "else", "end", "endcase", "endchecker",
|
||||
"endclass", "endclocking", "endconfig", "endfunction", "endgenerate", "endgroup", "endinterface", "endmodule", "endpackage",
|
||||
"endprimitive", "endprogram", "endproperty", "endsequence", "endspecify", "endtable", "endtask", "enum", "event", "eventually",
|
||||
"expect", "export", "extends", "extern", "final", "first_match", "for", "force", "foreach", "forever", "fork", "forkjoin", "function",
|
||||
"generate", "genvar", "global", "highz0", "highz1", "if", "iff", "ifnone", "ignore_bins", "illegal_bins", "implements", "implies",
|
||||
"import", "incdir", "include", "initial", "inout", "input", "inside", "instance", "int", "integer", "interconnect", "interface",
|
||||
"intersect", "join", "join_any", "join_none", "large", "let", "liblist", "library", "local", "localparam", "logic", "longint",
|
||||
"macromodule", "matches", "medium", "modport", "module", "nand", "negedge", "nettype", "new", "nexttime", "nmos", "nor",
|
||||
"noshowcancelled", "not", "notif0", "notif1", "null", "or", "output", "package", "packed", "parameter", "pmos", "posedge", "primitive",
|
||||
"priority", "program", "property", "protected", "pull0", "pull1", "pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent",
|
||||
"pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real", "realtime", "ref", "reg", "reject_on", "release", "repeat",
|
||||
"restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until",
|
||||
"s_until_with", "scalared", "sequence", "shortint", "shortreal", "showcancelled", "signed", "small", "soft", "solve", "specify",
|
||||
"specparam", "static", "string", "strong", "strong0", "strong1", "struct", "super", "supply0", "supply1", "sync_accept_on",
|
||||
"sync_reject_on", "table", "tagged", "task", "this", "throughout", "time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1",
|
||||
"tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef", "union", "unique", "unique0", "unsigned", "until", "until_with",
|
||||
"untyped", "use", "uwire", "var", "vectored", "virtual", "void", "wait", "wait_order", "wand", "weak", "weak0", "weak1", "while",
|
||||
"wildcard", "wire", "with", "within", "wor", "xnor", "xor",
|
||||
};
|
||||
if (keywords.count(str))
|
||||
do_escape = true;
|
||||
|
||||
if (do_escape)
|
||||
return "\\" + std::string(str) + " ";
|
||||
return std::string(str);
|
||||
|
@ -709,11 +736,14 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
|
||||
if (cell->type == "$shiftx")
|
||||
{
|
||||
std::string temp_id = next_auto_id();
|
||||
f << stringf("%s" "wire [%d:0] %s = ", indent.c_str(), GetSize(cell->getPort("\\A"))-1, temp_id.c_str());
|
||||
dump_sigspec(f, cell->getPort("\\A"));
|
||||
f << stringf(";\n");
|
||||
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort("\\Y"));
|
||||
f << stringf(" = ");
|
||||
dump_sigspec(f, cell->getPort("\\A"));
|
||||
f << stringf("[");
|
||||
f << stringf(" = %s[", temp_id.c_str());
|
||||
if (cell->getParam("\\B_SIGNED").as_bool())
|
||||
f << stringf("$signed(");
|
||||
dump_sigspec(f, cell->getPort("\\B"));
|
||||
|
@ -786,6 +816,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == "$tribuf")
|
||||
{
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
dump_sigspec(f, cell->getPort("\\Y"));
|
||||
f << stringf(" = ");
|
||||
dump_sigspec(f, cell->getPort("\\EN"));
|
||||
f << stringf(" ? ");
|
||||
dump_sigspec(f, cell->getPort("\\A"));
|
||||
f << stringf(" : %d'bz;\n", cell->parameters.at("\\WIDTH").as_int());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cell->type == "$slice")
|
||||
{
|
||||
f << stringf("%s" "assign ", indent.c_str());
|
||||
|
@ -1447,7 +1489,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
|||
}
|
||||
|
||||
if (!module->processes.empty())
|
||||
log_warning("Module %s contains unmapped RTLIL proccesses. RTLIL processes\n"
|
||||
log_warning("Module %s contains unmapped RTLIL processes. RTLIL processes\n"
|
||||
"can't always be mapped directly to Verilog always blocks. Unintended\n"
|
||||
"changes in simulation behavior are possible! Use \"proc\" to convert\n"
|
||||
"processes to logic networks and registers.\n", log_id(module));
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
/netlist.edn
|
||||
/netlist.vm
|
||||
/proj
|
|
@ -0,0 +1 @@
|
|||
# Add placement constraints here
|
|
@ -0,0 +1 @@
|
|||
# Add timing constraints here
|
|
@ -0,0 +1,23 @@
|
|||
module example (
|
||||
input clk,
|
||||
input EN,
|
||||
output LED1,
|
||||
output LED2,
|
||||
output LED3,
|
||||
output LED4,
|
||||
output LED5
|
||||
);
|
||||
|
||||
localparam BITS = 5;
|
||||
localparam LOG2DELAY = 22;
|
||||
|
||||
reg [BITS+LOG2DELAY-1:0] counter = 0;
|
||||
reg [BITS-1:0] outcnt;
|
||||
|
||||
always @(posedge clk) begin
|
||||
counter <= counter + EN;
|
||||
outcnt <= counter >> LOG2DELAY;
|
||||
end
|
||||
|
||||
assign {LED1, LED2, LED3, LED4, LED5} = outcnt ^ (outcnt >> 1);
|
||||
endmodule
|
|
@ -0,0 +1,53 @@
|
|||
# Run with "libero SCRIPT:libero.tcl"
|
||||
|
||||
file delete -force proj
|
||||
|
||||
new_project \
|
||||
-name example \
|
||||
-location proj \
|
||||
-block_mode 0 \
|
||||
-hdl "VERILOG" \
|
||||
-family IGLOO2 \
|
||||
-die PA4MGL500 \
|
||||
-package tq144 \
|
||||
-speed -1
|
||||
|
||||
import_files -hdl_source {netlist.vm}
|
||||
import_files -sdc {example.sdc}
|
||||
import_files -io_pdc {example.pdc}
|
||||
set_option -synth 0
|
||||
|
||||
organize_tool_files -tool PLACEROUTE \
|
||||
-file {proj/constraint/example.sdc} \
|
||||
-file {proj/constraint/io/example.pdc} \
|
||||
-input_type constraint
|
||||
|
||||
organize_tool_files -tool VERIFYTIMING \
|
||||
-file {proj/constraint/example.sdc} \
|
||||
-input_type constraint
|
||||
|
||||
configure_tool -name PLACEROUTE \
|
||||
-params TDPR:true \
|
||||
-params PDPR:false \
|
||||
-params EFFORT_LEVEL:false \
|
||||
-params REPAIR_MIN_DELAY:false
|
||||
|
||||
puts "**> COMPILE"
|
||||
run_tool -name {COMPILE}
|
||||
puts "<** COMPILE"
|
||||
|
||||
puts "**> PLACEROUTE"
|
||||
run_tool -name {PLACEROUTE}
|
||||
puts "<** PLACEROUTE"
|
||||
|
||||
puts "**> VERIFYTIMING"
|
||||
run_tool -name {VERIFYTIMING}
|
||||
puts "<** VERIFYTIMING"
|
||||
|
||||
save_project
|
||||
|
||||
# puts "**> export_bitstream"
|
||||
# export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
|
||||
# puts "<** export_bitstream"
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v
|
||||
LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v11.9/Libero/bin/libero SCRIPT:libero.tcl
|
|
@ -36,14 +36,14 @@ YOSYS_NAMESPACE_BEGIN
|
|||
using namespace AST;
|
||||
using namespace AST_INTERNAL;
|
||||
|
||||
// instanciate global variables (public API)
|
||||
// instantiate global variables (public API)
|
||||
namespace AST {
|
||||
std::string current_filename;
|
||||
void (*set_line_num)(int) = NULL;
|
||||
int (*get_line_num)() = NULL;
|
||||
}
|
||||
|
||||
// instanciate global variables (private API)
|
||||
// instantiate global variables (private API)
|
||||
namespace AST_INTERNAL {
|
||||
bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
|
||||
bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
|
||||
|
|
|
@ -276,7 +276,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, std::string dff_name, bo
|
|||
|
||||
if(lastcell == nullptr || module == nullptr)
|
||||
{
|
||||
err_reason = stringf("No primative object to attach .cname %s.", p);
|
||||
err_reason = stringf("No primitive object to attach .cname %s.", p);
|
||||
goto error_with_reason;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,11 +44,39 @@ struct IlangFrontend : public Frontend {
|
|||
log("Load modules from an ilang file to the current design. (ilang is a text\n");
|
||||
log("representation of a design in yosys's internal format.)\n");
|
||||
log("\n");
|
||||
log(" -nooverwrite\n");
|
||||
log(" ignore re-definitions of modules. (the default behavior is to\n");
|
||||
log(" create an error message if the existing module is not a blackbox\n");
|
||||
log(" module, and overwrite the existing module if it is a blackbox module.)\n");
|
||||
log("\n");
|
||||
log(" -overwrite\n");
|
||||
log(" overwrite existing modules with the same name\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
ILANG_FRONTEND::flag_nooverwrite = false;
|
||||
ILANG_FRONTEND::flag_overwrite = false;
|
||||
|
||||
log_header(design, "Executing ILANG frontend.\n");
|
||||
extra_args(f, filename, args, 1);
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
std::string arg = args[argidx];
|
||||
if (arg == "-nooverwrite") {
|
||||
ILANG_FRONTEND::flag_nooverwrite = true;
|
||||
ILANG_FRONTEND::flag_overwrite = false;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-overwrite") {
|
||||
ILANG_FRONTEND::flag_nooverwrite = false;
|
||||
ILANG_FRONTEND::flag_overwrite = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx);
|
||||
|
||||
log("Input filename: %s\n", filename.c_str());
|
||||
|
||||
ILANG_FRONTEND::lexin = f;
|
||||
|
|
|
@ -32,6 +32,8 @@ YOSYS_NAMESPACE_BEGIN
|
|||
namespace ILANG_FRONTEND {
|
||||
extern std::istream *lexin;
|
||||
extern RTLIL::Design *current_design;
|
||||
extern bool flag_nooverwrite;
|
||||
extern bool flag_overwrite;
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace ILANG_FRONTEND {
|
|||
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
|
||||
std::vector<RTLIL::CaseRule*> case_stack;
|
||||
dict<RTLIL::IdString, RTLIL::Const> attrbuf;
|
||||
bool flag_nooverwrite, flag_overwrite;
|
||||
bool delete_current_module;
|
||||
}
|
||||
using namespace ILANG_FRONTEND;
|
||||
YOSYS_NAMESPACE_END
|
||||
|
@ -93,18 +95,36 @@ design:
|
|||
|
||||
module:
|
||||
TOK_MODULE TOK_ID EOL {
|
||||
if (current_design->has($2))
|
||||
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str());
|
||||
delete_current_module = false;
|
||||
if (current_design->has($2)) {
|
||||
RTLIL::Module *existing_mod = current_design->module($2);
|
||||
if (!flag_overwrite && attrbuf.count("\\blackbox") && attrbuf.at("\\blackbox").as_bool()) {
|
||||
log("Ignoring blackbox re-definition of module %s.\n", $2);
|
||||
delete_current_module = true;
|
||||
} else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
|
||||
rtlil_frontend_ilang_yyerror(stringf("ilang error: redefinition of module %s.", $2).c_str());
|
||||
} else if (flag_nooverwrite) {
|
||||
log("Ignoring re-definition of module %s.\n", $2);
|
||||
delete_current_module = true;
|
||||
} else {
|
||||
log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "", $2);
|
||||
current_design->remove(existing_mod);
|
||||
}
|
||||
}
|
||||
current_module = new RTLIL::Module;
|
||||
current_module->name = $2;
|
||||
current_module->attributes = attrbuf;
|
||||
current_design->add(current_module);
|
||||
if (!delete_current_module)
|
||||
current_design->add(current_module);
|
||||
attrbuf.clear();
|
||||
free($2);
|
||||
} module_body TOK_END {
|
||||
if (attrbuf.size() != 0)
|
||||
rtlil_frontend_ilang_yyerror("dangling attribute");
|
||||
current_module->fixup_ports();
|
||||
if (delete_current_module)
|
||||
delete current_module;
|
||||
current_module = nullptr;
|
||||
} EOL;
|
||||
|
||||
module_body:
|
||||
|
|
|
@ -616,7 +616,7 @@ struct LibertyFrontend : public Frontend {
|
|||
LibertyAst *bus_type_node = node->find("bus_type");
|
||||
|
||||
if (!bus_type_node || !type_map.count(bus_type_node->value))
|
||||
log_error("Unkown or unsupported type for bus interface %s on cell %s.\n",
|
||||
log_error("Unknown or unsupported type for bus interface %s on cell %s.\n",
|
||||
node->args.at(0).c_str(), log_id(cell_name));
|
||||
|
||||
int bus_type_width = std::get<0>(type_map.at(bus_type_node->value));
|
||||
|
|
|
@ -4,35 +4,6 @@ This directory contains Verific bindings for Yosys.
|
|||
See http://www.verific.com/ for details.
|
||||
|
||||
|
||||
Building Yosys with the 32 bit Verific eval library on amd64:
|
||||
=============================================================
|
||||
|
||||
1.) Use a Makefile.conf like the following one:
|
||||
|
||||
--snip--
|
||||
CONFIG := gcc
|
||||
ENABLE_TCL := 0
|
||||
ENABLE_PLUGINS := 0
|
||||
ENABLE_VERIFIC := 1
|
||||
CXXFLAGS += -m32
|
||||
LDFLAGS += -m32
|
||||
VERIFIC_DIR = /usr/local/src/verific_lib_eval
|
||||
--snap--
|
||||
|
||||
|
||||
2.) Install the necessary multilib packages
|
||||
|
||||
Hint: On debian/ubuntu the multilib packages have names such as
|
||||
libreadline-dev:i386 or lib32readline6-dev, depending on the
|
||||
exact version of debian/ubuntu you are working with.
|
||||
|
||||
|
||||
3.) Build and test
|
||||
|
||||
make -j8
|
||||
./yosys -p 'verific -sv frontends/verific/example.sv; verific -import top'
|
||||
|
||||
|
||||
Verific Features that should be enabled in your Verific library
|
||||
===============================================================
|
||||
|
||||
|
|
|
@ -1200,27 +1200,34 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
|
|||
if (inst->Type() == OPER_WRITE_PORT || inst->Type() == OPER_CLOCKED_WRITE_PORT)
|
||||
{
|
||||
RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name()));
|
||||
if (memory->width != int(inst->Input2Size()))
|
||||
log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name());
|
||||
int numchunks = int(inst->Input2Size()) / memory->width;
|
||||
int chunksbits = ceil_log2(numchunks);
|
||||
|
||||
RTLIL::SigSpec addr = operatorInput1(inst);
|
||||
RTLIL::SigSpec data = operatorInput2(inst);
|
||||
if ((numchunks * memory->width) != int(inst->Input2Size()) || (numchunks & (numchunks - 1)) != 0)
|
||||
log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetOutput()->Name());
|
||||
|
||||
RTLIL::Cell *cell = module->addCell(inst_name, "$memwr");
|
||||
cell->parameters["\\MEMID"] = memory->name.str();
|
||||
cell->parameters["\\CLK_ENABLE"] = false;
|
||||
cell->parameters["\\CLK_POLARITY"] = true;
|
||||
cell->parameters["\\PRIORITY"] = 0;
|
||||
cell->parameters["\\ABITS"] = GetSize(addr);
|
||||
cell->parameters["\\WIDTH"] = GetSize(data);
|
||||
cell->setPort("\\EN", RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data)));
|
||||
cell->setPort("\\CLK", RTLIL::State::S0);
|
||||
cell->setPort("\\ADDR", addr);
|
||||
cell->setPort("\\DATA", data);
|
||||
for (int i = 0; i < numchunks; i++)
|
||||
{
|
||||
RTLIL::SigSpec addr = {operatorInput1(inst), RTLIL::Const(i, chunksbits)};
|
||||
RTLIL::SigSpec data = operatorInput2(inst).extract(i * memory->width, memory->width);
|
||||
|
||||
if (inst->Type() == OPER_CLOCKED_WRITE_PORT) {
|
||||
cell->parameters["\\CLK_ENABLE"] = true;
|
||||
cell->setPort("\\CLK", net_map_at(inst->GetClock()));
|
||||
RTLIL::Cell *cell = module->addCell(numchunks == 1 ? inst_name :
|
||||
RTLIL::IdString(stringf("%s_%d", inst_name.c_str(), i)), "$memwr");
|
||||
cell->parameters["\\MEMID"] = memory->name.str();
|
||||
cell->parameters["\\CLK_ENABLE"] = false;
|
||||
cell->parameters["\\CLK_POLARITY"] = true;
|
||||
cell->parameters["\\PRIORITY"] = 0;
|
||||
cell->parameters["\\ABITS"] = GetSize(addr);
|
||||
cell->parameters["\\WIDTH"] = GetSize(data);
|
||||
cell->setPort("\\EN", RTLIL::SigSpec(net_map_at(inst->GetControl())).repeat(GetSize(data)));
|
||||
cell->setPort("\\CLK", RTLIL::State::S0);
|
||||
cell->setPort("\\ADDR", addr);
|
||||
cell->setPort("\\DATA", data);
|
||||
|
||||
if (inst->Type() == OPER_CLOCKED_WRITE_PORT) {
|
||||
cell->parameters["\\CLK_ENABLE"] = true;
|
||||
cell->setPort("\\CLK", net_map_at(inst->GetClock()));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1893,13 +1900,19 @@ struct VerificPass : public Pass {
|
|||
{
|
||||
Message::SetConsoleOutput(0);
|
||||
Message::RegisterCallBackMsg(msg_func);
|
||||
|
||||
RuntimeFlags::SetVar("db_preserve_user_nets", 1);
|
||||
RuntimeFlags::SetVar("db_allow_external_nets", 1);
|
||||
RuntimeFlags::SetVar("vhdl_support_variable_slice", 1);
|
||||
RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);
|
||||
RuntimeFlags::SetVar("db_infer_wide_operators", 1);
|
||||
|
||||
RuntimeFlags::SetVar("veri_extract_dualport_rams", 0);
|
||||
RuntimeFlags::SetVar("veri_extract_multiport_rams", 1);
|
||||
RuntimeFlags::SetVar("db_infer_wide_operators", 1);
|
||||
|
||||
RuntimeFlags::SetVar("vhdl_extract_dualport_rams", 0);
|
||||
RuntimeFlags::SetVar("vhdl_extract_multiport_rams", 1);
|
||||
|
||||
RuntimeFlags::SetVar("vhdl_support_variable_slice", 1);
|
||||
RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);
|
||||
|
||||
// Workaround for VIPER #13851
|
||||
RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1);
|
||||
|
|
|
@ -827,9 +827,9 @@ struct SvaFsm
|
|||
|
||||
for (auto &it : nodes[i].edges) {
|
||||
if (it.second != State::S1)
|
||||
log(" egde %s -> %d\n", log_signal(it.second), it.first);
|
||||
log(" edge %s -> %d\n", log_signal(it.second), it.first);
|
||||
else
|
||||
log(" egde -> %d\n", it.first);
|
||||
log(" edge -> %d\n", it.first);
|
||||
}
|
||||
|
||||
for (auto &it : nodes[i].links) {
|
||||
|
@ -856,9 +856,9 @@ struct SvaFsm
|
|||
|
||||
for (auto &it : unodes[i].edges) {
|
||||
if (!it.second.empty())
|
||||
log(" egde %s -> %d\n", log_signal(it.second), it.first);
|
||||
log(" edge %s -> %d\n", log_signal(it.second), it.first);
|
||||
else
|
||||
log(" egde -> %d\n", it.first);
|
||||
log(" edge -> %d\n", it.first);
|
||||
}
|
||||
|
||||
for (auto &ctrl : unodes[i].accept) {
|
||||
|
|
|
@ -274,7 +274,7 @@ YOSYS_NAMESPACE_END
|
|||
yystr[j++] = yystr[i++];
|
||||
}
|
||||
yystr[j] = 0;
|
||||
frontend_verilog_yylval.string = new std::string(yystr);
|
||||
frontend_verilog_yylval.string = new std::string(yystr, j);
|
||||
free(yystr);
|
||||
return TOK_STRING;
|
||||
}
|
||||
|
|
|
@ -794,7 +794,7 @@ more_path_inputs :
|
|||
list_of_path_outputs :
|
||||
specify_output_terminal_descriptor |
|
||||
list_of_path_outputs ',' specify_output_terminal_descriptor ;
|
||||
|
||||
|
||||
opt_polarity_operator :
|
||||
'+'
|
||||
| '-'
|
||||
|
@ -819,7 +819,7 @@ system_timing_arg :
|
|||
system_timing_args :
|
||||
system_timing_arg |
|
||||
system_timing_args ',' system_timing_arg ;
|
||||
|
||||
|
||||
/*
|
||||
t_path_delay_expression :
|
||||
path_delay_expression;
|
||||
|
@ -881,7 +881,7 @@ constant_mintypmax_expression :
|
|||
// for the time being this is OK, but we may write our own expr here.
|
||||
// as I'm not sure it is legal to use a full expr here (probably not)
|
||||
// On the other hand, other rules requiring constant expressions also use 'expr'
|
||||
// (such as param assignment), so we may leave this as-is, perhaps assing runtime checks for constant-ness
|
||||
// (such as param assignment), so we may leave this as-is, perhaps adding runtime checks for constant-ness
|
||||
constant_expression:
|
||||
expr ;
|
||||
|
||||
|
|
|
@ -94,7 +94,9 @@ const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
|
|||
const char *log_const(const RTLIL::Const &value, bool autoint = true);
|
||||
const char *log_id(RTLIL::IdString id);
|
||||
|
||||
template<typename T> static inline const char *log_id(T *obj) {
|
||||
template<typename T> static inline const char *log_id(T *obj, const char *nullstr = nullptr) {
|
||||
if (nullstr && obj == nullptr)
|
||||
return nullstr;
|
||||
return log_id(obj->name);
|
||||
}
|
||||
|
||||
|
@ -195,7 +197,7 @@ struct PerformanceTimer
|
|||
t += 1000000000ULL * (int64_t) rusage.ru_stime.tv_sec + (int64_t) rusage.ru_stime.tv_usec * 1000ULL;
|
||||
return t;
|
||||
# else
|
||||
# error Dont know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?).
|
||||
# error "Don't know how to measure per-process CPU time. Need alternative method (times()/clocks()/gettimeofday()?)."
|
||||
# endif
|
||||
}
|
||||
|
||||
|
|
|
@ -3793,6 +3793,11 @@ RTLIL::CaseRule::~CaseRule()
|
|||
delete *it;
|
||||
}
|
||||
|
||||
bool RTLIL::CaseRule::empty() const
|
||||
{
|
||||
return actions.empty() && switches.empty();
|
||||
}
|
||||
|
||||
RTLIL::CaseRule *RTLIL::CaseRule::clone() const
|
||||
{
|
||||
RTLIL::CaseRule *new_caserule = new RTLIL::CaseRule;
|
||||
|
@ -3809,6 +3814,11 @@ RTLIL::SwitchRule::~SwitchRule()
|
|||
delete *it;
|
||||
}
|
||||
|
||||
bool RTLIL::SwitchRule::empty() const
|
||||
{
|
||||
return cases.empty();
|
||||
}
|
||||
|
||||
RTLIL::SwitchRule *RTLIL::SwitchRule::clone() const
|
||||
{
|
||||
RTLIL::SwitchRule *new_switchrule = new RTLIL::SwitchRule;
|
||||
|
|
|
@ -1227,6 +1227,8 @@ struct RTLIL::CaseRule
|
|||
~CaseRule();
|
||||
void optimize();
|
||||
|
||||
bool empty() const;
|
||||
|
||||
template<typename T> void rewrite_sigspecs(T &functor);
|
||||
RTLIL::CaseRule *clone() const;
|
||||
};
|
||||
|
@ -1238,6 +1240,8 @@ struct RTLIL::SwitchRule : public RTLIL::AttrObject
|
|||
|
||||
~SwitchRule();
|
||||
|
||||
bool empty() const;
|
||||
|
||||
template<typename T> void rewrite_sigspecs(T &functor);
|
||||
RTLIL::SwitchRule *clone() const;
|
||||
};
|
||||
|
|
|
@ -166,7 +166,7 @@ std::string vstringf(const char *fmt, va_list ap)
|
|||
std::string string;
|
||||
char *str = NULL;
|
||||
|
||||
#if defined(_WIN32 )|| defined(__CYGWIN__)
|
||||
#if defined(_WIN32 )|| defined(__CYGWIN__)
|
||||
int sz = 64, rc;
|
||||
while (1) {
|
||||
va_list apc;
|
||||
|
@ -637,8 +637,9 @@ extern Tcl_Interp *yosys_get_tcl_interp()
|
|||
struct TclPass : public Pass {
|
||||
TclPass() : Pass("tcl", "execute a TCL script file") { }
|
||||
void help() YS_OVERRIDE {
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" tcl <filename>\n");
|
||||
log(" tcl <filename> [args]\n");
|
||||
log("\n");
|
||||
log("This command executes the tcl commands in the specified file.\n");
|
||||
log("Use 'yosys cmd' to run the yosys command 'cmd' from tcl.\n");
|
||||
|
@ -648,14 +649,24 @@ struct TclPass : public Pass {
|
|||
log("'proc' and 'rename' are wrapped to tcl commands 'procs' and 'renames'\n");
|
||||
log("in order to avoid a name collision with the built in commands.\n");
|
||||
log("\n");
|
||||
log("If any arguments are specified, these arguments are provided to the script via\n");
|
||||
log("the standard $argc and $argv variables.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *) YS_OVERRIDE {
|
||||
if (args.size() < 2)
|
||||
log_cmd_error("Missing script file.\n");
|
||||
if (args.size() > 2)
|
||||
extra_args(args, 1, design, false);
|
||||
if (Tcl_EvalFile(yosys_get_tcl_interp(), args[1].c_str()) != TCL_OK)
|
||||
log_cmd_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(yosys_get_tcl_interp()));
|
||||
|
||||
std::vector<Tcl_Obj*> script_args;
|
||||
for (auto it = args.begin() + 2; it != args.end(); ++it)
|
||||
script_args.push_back(Tcl_NewStringObj((*it).c_str(), (*it).size()));
|
||||
|
||||
Tcl_Interp *interp = yosys_get_tcl_interp();
|
||||
Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argc", 4), NULL, Tcl_NewIntObj(script_args.size()), 0);
|
||||
Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv", 4), NULL, Tcl_NewListObj(script_args.size(), script_args.data()), 0);
|
||||
Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv0", 5), NULL, Tcl_NewStringObj(args[1].c_str(), args[1].size()), 0);
|
||||
if (Tcl_EvalFile(interp, args[1].c_str()) != TCL_OK)
|
||||
log_cmd_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(interp));
|
||||
}
|
||||
} TclPass;
|
||||
#endif
|
||||
|
@ -733,7 +744,7 @@ std::string proc_self_dirname()
|
|||
return "/";
|
||||
}
|
||||
#else
|
||||
#error Dont know how to determine process executable base path!
|
||||
#error "Don't know how to determine process executable base path!"
|
||||
#endif
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <time.h>
|
||||
|
||||
// minisat is using limit macros and format macros in their headers that
|
||||
// can be the source of some troubles when used from c++11. thefore we
|
||||
// can be the source of some troubles when used from c++11. therefore we
|
||||
// don't force ezSAT users to use minisat headers..
|
||||
namespace Minisat {
|
||||
class Solver;
|
||||
|
|
|
@ -109,7 +109,7 @@ look at the demo.cc example program in this directory.
|
|||
Setting up graphs
|
||||
-----------------
|
||||
|
||||
Instanciate the SubCircuit::Graph class and use the methods of this class to
|
||||
Instantiate the SubCircuit::Graph class and use the methods of this class to
|
||||
set up the circuit.
|
||||
|
||||
SubCircuit::Graph myGraph;
|
||||
|
@ -152,7 +152,7 @@ rotate shift,
|
|||
|
||||
The method createConstant() can be used to add a constant driver to a signal.
|
||||
The signal value is encoded as one char by bit, allowing for multi-valued
|
||||
logic matching. The follwoing command sets the lowest bit of cell6.A to a
|
||||
logic matching. The following command sets the lowest bit of cell6.A to a
|
||||
logic 1:
|
||||
|
||||
myGraph.createConnection("cell6", "A", 0, '1');
|
||||
|
@ -314,7 +314,7 @@ bool userCompareEdge(needleGraphId, needleFromNodeId, needleFromUserData, needle
|
|||
|
||||
Perform additional checks on a pair of a pair of adjacent nodes (one
|
||||
adjacent pair from the needle and one adjacent pair from the haystack)
|
||||
to determine wheter this edge from the needle is compatible with
|
||||
to determine whether this edge from the needle is compatible with
|
||||
that edge from the haystack. The default implementation always
|
||||
returns true.
|
||||
|
||||
|
|
|
@ -119,6 +119,12 @@ than one bit from \B{S} is set the output is undefined. Cells of this type are u
|
|||
``parallel cases'' (defined by using the {\tt parallel\_case} attribute or detected by
|
||||
an optimization).
|
||||
|
||||
The {\tt \$tribuf} cell is used to implement tristate logic. Cells of this type have a \B{WIDTH}
|
||||
parameter and inputs \B{A} and \B{EN} and an output \B{Y}. The \B{A} input and \B{Y} output are
|
||||
\B{WIDTH} bits wide, and the \B{EN} input is one bit wide. When \B{EN} is 0, the output \B{Y}
|
||||
is not driven. When \B{EN} is 1, the value from \B{A} input is sent to the \B{Y} output. Therefore,
|
||||
the {\tt \$tribuf} cell implements the function \lstinline[language=Verilog]; Y = EN ? A : 'bz;.
|
||||
|
||||
Behavioural code with cascaded {\tt if-then-else}- and {\tt case}-statements
|
||||
usually results in trees of multiplexer cells. Many passes (from various
|
||||
optimizations to FSM extraction) heavily depend on these multiplexer trees to
|
||||
|
@ -211,14 +217,15 @@ Add information about {\tt \$sr} cells (set-reset flip-flops) and d-type latches
|
|||
\subsection{Memories}
|
||||
\label{sec:memcells}
|
||||
|
||||
Memories are either represented using RTLIL::Memory objects and {\tt \$memrd} and {\tt \$memwr} cells
|
||||
or simply by using {\tt \$mem} cells.
|
||||
Memories are either represented using RTLIL::Memory objects, {\tt \$memrd}, {\tt \$memwr}, and {\tt \$meminit}
|
||||
cells, or by {\tt \$mem} cells alone.
|
||||
|
||||
In the first alternative the RTLIL::Memory objects hold the general metadata for the memory (bit width,
|
||||
size in number of words, etc.) and for each port a {\tt \$memrd} (read port) or {\tt \$memwr} (write port)
|
||||
cell is created. Having individual cells for read and write ports has the advantage that they can be
|
||||
consolidated using resource sharing passes. In some cases this drastically reduces the number of required
|
||||
ports on the memory cell.
|
||||
ports on the memory cell. In this alternative, memory initialization data is represented by {\tt \$meminit} cells,
|
||||
which allow delaying constant folding for initialization addresses and data until after the frontend finishes.
|
||||
|
||||
The {\tt \$memrd} cells have a clock input \B{CLK}, an enable input \B{EN}, an
|
||||
address input \B{ADDR}, and a data output \B{DATA}. They also have the
|
||||
|
@ -253,7 +260,7 @@ enable bit for each data bit), an address input \B{ADDR} and a data input
|
|||
|
||||
\begin{itemize}
|
||||
\item \B{MEMID} \\
|
||||
The name of the RTLIL::Memory object that is associated with this read port.
|
||||
The name of the RTLIL::Memory object that is associated with this write port.
|
||||
|
||||
\item \B{ABITS} \\
|
||||
The number of address bits (width of the \B{ADDR} input port).
|
||||
|
@ -262,7 +269,7 @@ The number of address bits (width of the \B{ADDR} input port).
|
|||
The number of data bits (width of the \B{DATA} output port).
|
||||
|
||||
\item \B{CLK\_ENABLE} \\
|
||||
When this parameter is non-zero, the clock is used. Otherwise this read port is asynchronous and
|
||||
When this parameter is non-zero, the clock is used. Otherwise this write port is asynchronous and
|
||||
the \B{CLK} input is not used.
|
||||
|
||||
\item \B{CLK\_POLARITY} \\
|
||||
|
@ -273,6 +280,27 @@ edge if this parameter is {\tt 1'b0}.
|
|||
The cell with the higher integer value in this parameter wins a write conflict.
|
||||
\end{itemize}
|
||||
|
||||
The {\tt \$meminit} cells have an address input \B{ADDR} and a data input \B{DATA}, with the width
|
||||
of the \B{DATA} port equal to \B{WIDTH} parameter times \B{WORDS} parameter. Both of the inputs
|
||||
must resolve to a constant for synthesis to succeed.
|
||||
|
||||
\begin{itemize}
|
||||
\item \B{MEMID} \\
|
||||
The name of the RTLIL::Memory object that is associated with this initialization cell.
|
||||
|
||||
\item \B{ABITS} \\
|
||||
The number of address bits (width of the \B{ADDR} input port).
|
||||
|
||||
\item \B{WIDTH} \\
|
||||
The number of data bits per memory location.
|
||||
|
||||
\item \B{WORDS} \\
|
||||
The number of consecutive memory locations initialized by this cell.
|
||||
|
||||
\item \B{PRIORITY} \\
|
||||
The cell with the higher integer value in this parameter wins an initialization conflict.
|
||||
\end{itemize}
|
||||
|
||||
The HDL frontend models a memory using RTLIL::Memory objects and asynchronous
|
||||
{\tt \$memrd} and {\tt \$memwr} cells. The {\tt memory} pass (i.e.~its various sub-passes) migrates
|
||||
{\tt \$dff} cells into the {\tt \$memrd} and {\tt \$memwr} cells making them synchronous, then
|
||||
|
@ -295,6 +323,9 @@ The number of address bits.
|
|||
\item \B{WIDTH} \\
|
||||
The number of data bits per word.
|
||||
|
||||
\item \B{INIT} \\
|
||||
The initial memory contents.
|
||||
|
||||
\item \B{RD\_PORTS} \\
|
||||
The number of read ports on this memory cell.
|
||||
|
||||
|
@ -345,9 +376,11 @@ This input is \B{WR\_PORTS}*\B{ABITS} bits wide, containing all address signals
|
|||
This input is \B{WR\_PORTS}*\B{WIDTH} bits wide, containing all data signals for the write ports.
|
||||
\end{itemize}
|
||||
|
||||
The {\tt techmap} pass can be used to manually map {\tt \$mem} cells to
|
||||
specialized memory cells on the target architecture, such as block ram resources
|
||||
on an FPGA.
|
||||
The {\tt memory\_collect} pass can be used to convert discrete {\tt \$memrd}, {\tt \$memwr}, and {\tt \$meminit} cells
|
||||
belonging to the same memory to a single {\tt \$mem} cell, whereas the {\tt memory\_unpack} pass performs the inverse operation.
|
||||
The {\tt memory\_dff} pass can combine asynchronous memory ports that are fed by or feeding registers into synchronous memory ports.
|
||||
The {\tt memory\_bram} pass can be used to recognize {\tt \$mem} cells that can be implemented with a block RAM resource on an FPGA.
|
||||
The {\tt memory\_map} pass can be used to implement {\tt \$mem} cells as basic logic: word-wide DFFs and address decoders.
|
||||
|
||||
\subsection{Finite State Machines}
|
||||
|
||||
|
@ -371,9 +404,15 @@ Verilog & Cell Type \\
|
|||
\hline
|
||||
\lstinline[language=Verilog]; Y = ~A; & {\tt \$\_NOT\_} \\
|
||||
\lstinline[language=Verilog]; Y = A & B; & {\tt \$\_AND\_} \\
|
||||
\lstinline[language=Verilog]; Y = ~(A & B); & {\tt \$\_NAND\_} \\
|
||||
\lstinline[language=Verilog]; Y = A & ~B; & {\tt \$\_ANDNOT\_} \\
|
||||
\lstinline[language=Verilog]; Y = A | B; & {\tt \$\_OR\_} \\
|
||||
\lstinline[language=Verilog]; Y = ~(A | B); & {\tt \$\_NOR\_} \\
|
||||
\lstinline[language=Verilog]; Y = A | ~B; & {\tt \$\_ORNOT\_} \\
|
||||
\lstinline[language=Verilog]; Y = A ^ B; & {\tt \$\_XOR\_} \\
|
||||
\lstinline[language=Verilog]; Y = ~(A ^ B); & {\tt \$\_XNOR\_} \\
|
||||
\lstinline[language=Verilog]; Y = S ? B : A; & {\tt \$\_MUX\_} \\
|
||||
\lstinline[language=Verilog]; Y = EN ? A : 'bz; & {\tt \$\_TBUF\_} \\
|
||||
\hline
|
||||
\lstinline[language=Verilog]; always @(negedge C) Q <= D; & {\tt \$\_DFF\_N\_} \\
|
||||
\lstinline[language=Verilog]; always @(posedge C) Q <= D; & {\tt \$\_DFF\_P\_} \\
|
||||
|
@ -396,9 +435,10 @@ $ClkEdge$ & $RstLvl$ & $RstVal$ & Cell Type \\
|
|||
\end{table}
|
||||
|
||||
Table~\ref{tab:CellLib_gates} lists all cell types used for gate level logic. The cell types
|
||||
{\tt \$\_NOT\_}, {\tt \$\_AND\_}, {\tt \$\_OR\_}, {\tt \$\_XOR\_} and {\tt \$\_MUX\_}
|
||||
are used to model combinatorial logic. The cell types {\tt \$\_DFF\_N\_} and {\tt \$\_DFF\_P\_}
|
||||
represent d-type flip-flops.
|
||||
{\tt \$\_NOT\_}, {\tt \$\_AND\_}, {\tt \$\_NAND\_}, {\tt \$\_ANDNOT\_}, {\tt \$\_OR\_}, {\tt \$\_NOR\_},
|
||||
{\tt \$\_ORNOT\_}, {\tt \$\_XOR\_}, {\tt \$\_XNOR\_} and {\tt \$\_MUX\_} are used to model combinatorial logic.
|
||||
The cell type {\tt \$\_TBUF\_} is used to model tristate logic.
|
||||
The cell types {\tt \$\_DFF\_N\_} and {\tt \$\_DFF\_P\_} represent d-type flip-flops.
|
||||
|
||||
The cell types {\tt \$\_DFF\_NN0\_}, {\tt \$\_DFF\_NN1\_}, {\tt \$\_DFF\_NP0\_}, {\tt \$\_DFF\_NP1\_},
|
||||
{\tt \$\_DFF\_PN0\_}, {\tt \$\_DFF\_PN1\_}, {\tt \$\_DFF\_PP0\_} and {\tt \$\_DFF\_PP1\_} implement
|
||||
|
@ -410,7 +450,7 @@ otherwise.
|
|||
\begin{lstlisting}[mathescape,language=Verilog]
|
||||
always @($ClkEdge$ C, $RstEdge$ R)
|
||||
if (R == $RstLvl$)
|
||||
Q <= $RstVa$l;
|
||||
Q <= $RstVal$;
|
||||
else
|
||||
Q <= D;
|
||||
\end{lstlisting}
|
||||
|
@ -450,7 +490,6 @@ Add information about {\tt \$\_DFFE\_??\_}, {\tt \$\_DFFSR\_???\_}, {\tt \$\_DLA
|
|||
\end{fixme}
|
||||
|
||||
\begin{fixme}
|
||||
Add information about {\tt \$\_NAND\_}, {\tt \$\_NOR\_}, {\tt \$\_XNOR\_}, {\tt \$\_ANDNOT\_}, {\tt \$\_ORNOT\_},
|
||||
{\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells.
|
||||
Add information about {\tt \$\_AOI3\_}, {\tt \$\_OAI3\_}, {\tt \$\_AOI4\_}, and {\tt \$\_OAI4\_} cells.
|
||||
\end{fixme}
|
||||
|
||||
|
|
|
@ -428,8 +428,8 @@ memory object has the following properties:
|
|||
|
||||
All read accesses to the memory are transformed to {\tt \$memrd} cells and all write accesses to
|
||||
{\tt \$memwr} cells by the language frontend. These cells consist of independent read- and write-ports
|
||||
to the memory. The \B{MEMID} parameter on these cells is used to link them together and to the
|
||||
RTLIL::Memory object they belong to.
|
||||
to the memory. Memory initialization is transformed to {\tt \$meminit} cells by the language frontend.
|
||||
The \B{MEMID} parameter on these cells is used to link them together and to the RTLIL::Memory object they belong to.
|
||||
|
||||
The rationale behind using separate cells for the individual ports versus
|
||||
creating a large multiport memory cell right in the language frontend is that
|
||||
|
|
|
@ -29,4 +29,4 @@ OBJS += passes/cmds/chformal.o
|
|||
OBJS += passes/cmds/chtype.o
|
||||
OBJS += passes/cmds/blackbox.o
|
||||
OBJS += passes/cmds/ltp.o
|
||||
|
||||
OBJS += passes/cmds/bugpoint.o
|
||||
|
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2018 whitequark <whitequark@whitequark.org>
|
||||
*
|
||||
* 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/yosys.h"
|
||||
#include "backends/ilang/ilang_backend.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
using namespace ILANG_BACKEND;
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct BugpointPass : public Pass {
|
||||
BugpointPass() : Pass("bugpoint", "minimize testcases") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" bugpoint [options]\n");
|
||||
log("\n");
|
||||
log("This command minimizes testcases that crash Yosys. It removes an arbitrary part\n");
|
||||
log("of the design and recursively invokes Yosys with a given script, repeating these\n");
|
||||
log("steps while it can find a smaller design that still causes a crash. Once this\n");
|
||||
log("command finishes, it replaces the current design with the smallest testcase it\n");
|
||||
log("was able to produce.\n");
|
||||
log("\n");
|
||||
log("It is possible to specify the kinds of design part that will be removed. If none\n");
|
||||
log("are specified, all parts of design will be removed.\n");
|
||||
log("\n");
|
||||
log(" -yosys <filename>\n");
|
||||
log(" use this Yosys binary. if not specified, `yosys` is used.\n");
|
||||
log("\n");
|
||||
log(" -script <filename>\n");
|
||||
log(" use this script to crash Yosys. required.\n");
|
||||
log("\n");
|
||||
log(" -grep <string>\n");
|
||||
log(" only consider crashes that place this string in the log file.\n");
|
||||
log("\n");
|
||||
log(" -fast\n");
|
||||
log(" run `clean -purge` after each minimization step. converges faster, but\n");
|
||||
log(" produces larger testcases, and may fail to produce any testcase at all if\n");
|
||||
log(" the crash is related to dangling wires.\n");
|
||||
log("\n");
|
||||
log(" -clean\n");
|
||||
log(" run `clean -purge` before checking testcase and after finishing. produces\n");
|
||||
log(" smaller and more useful testcases, but may fail to produce any testcase\n");
|
||||
log(" at all if the crash is related to dangling wires.\n");
|
||||
log("\n");
|
||||
log(" -modules\n");
|
||||
log(" try to remove modules.\n");
|
||||
log("\n");
|
||||
log(" -ports\n");
|
||||
log(" try to remove module ports.\n");
|
||||
log("\n");
|
||||
log(" -cells\n");
|
||||
log(" try to remove cells.\n");
|
||||
log("\n");
|
||||
log(" -connections\n");
|
||||
log(" try to reconnect ports to 'x.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
bool run_yosys(RTLIL::Design *design, string yosys_cmd, string script)
|
||||
{
|
||||
design->sort();
|
||||
|
||||
std::ofstream f("bugpoint-case.il");
|
||||
ILANG_BACKEND::dump_design(f, design, /*only_selected=*/false, /*flag_m=*/true, /*flag_n=*/false);
|
||||
f.close();
|
||||
|
||||
string yosys_cmdline = stringf("%s -qq -L bugpoint-case.log -s %s bugpoint-case.il", yosys_cmd.c_str(), script.c_str());
|
||||
return run_command(yosys_cmdline) == 0;
|
||||
}
|
||||
|
||||
bool check_logfile(string grep)
|
||||
{
|
||||
if (grep.empty())
|
||||
return true;
|
||||
|
||||
std::ifstream f("bugpoint-case.log");
|
||||
while (!f.eof())
|
||||
{
|
||||
string line;
|
||||
getline(f, line);
|
||||
if (line.find(grep) != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RTLIL::Design *clean_design(RTLIL::Design *design, bool do_clean = true, bool do_delete = false)
|
||||
{
|
||||
if (!do_clean)
|
||||
return design;
|
||||
|
||||
RTLIL::Design *design_copy = new RTLIL::Design;
|
||||
for (auto &it : design->modules_)
|
||||
design_copy->add(it.second->clone());
|
||||
Pass::call(design_copy, "clean -purge");
|
||||
|
||||
if (do_delete)
|
||||
delete design;
|
||||
return design_copy;
|
||||
}
|
||||
|
||||
RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections)
|
||||
{
|
||||
RTLIL::Design *design_copy = new RTLIL::Design;
|
||||
for (auto &it : design->modules_)
|
||||
design_copy->add(it.second->clone());
|
||||
|
||||
int index = 0;
|
||||
if (modules)
|
||||
{
|
||||
for (auto &it : design_copy->modules_)
|
||||
{
|
||||
if (it.second->get_bool_attribute("\\blackbox"))
|
||||
continue;
|
||||
|
||||
if (index++ == seed)
|
||||
{
|
||||
log("Trying to remove module %s.\n", it.first.c_str());
|
||||
design_copy->remove(it.second);
|
||||
return design_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ports)
|
||||
{
|
||||
for (auto mod : design_copy->modules())
|
||||
{
|
||||
if (mod->get_bool_attribute("\\blackbox"))
|
||||
continue;
|
||||
|
||||
for (auto wire : mod->wires())
|
||||
{
|
||||
if (!stage2 && wire->get_bool_attribute("$bugpoint"))
|
||||
continue;
|
||||
|
||||
if (wire->port_input || wire->port_output)
|
||||
{
|
||||
if (index++ == seed)
|
||||
{
|
||||
log("Trying to remove module port %s.\n", log_signal(wire));
|
||||
wire->port_input = wire->port_output = false;
|
||||
mod->fixup_ports();
|
||||
return design_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cells)
|
||||
{
|
||||
for (auto mod : design_copy->modules())
|
||||
{
|
||||
if (mod->get_bool_attribute("\\blackbox"))
|
||||
continue;
|
||||
|
||||
for (auto &it : mod->cells_)
|
||||
{
|
||||
if (index++ == seed)
|
||||
{
|
||||
log("Trying to remove cell %s.%s.\n", mod->name.c_str(), it.first.c_str());
|
||||
mod->remove(it.second);
|
||||
return design_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (connections)
|
||||
{
|
||||
for (auto mod : design_copy->modules())
|
||||
{
|
||||
if (mod->get_bool_attribute("\\blackbox"))
|
||||
continue;
|
||||
|
||||
for (auto cell : mod->cells())
|
||||
{
|
||||
for (auto it : cell->connections_)
|
||||
{
|
||||
RTLIL::SigSpec port = cell->getPort(it.first);
|
||||
bool is_undef = port.is_fully_undef();
|
||||
bool is_port = port.is_wire() && (port.as_wire()->port_input || port.as_wire()->port_output);
|
||||
|
||||
if(is_undef || (!stage2 && is_port))
|
||||
continue;
|
||||
|
||||
if (index++ == seed)
|
||||
{
|
||||
log("Trying to remove cell port %s.%s.%s.\n", mod->name.c_str(), cell->name.c_str(), it.first.c_str());
|
||||
RTLIL::SigSpec port_x(State::Sx, port.size());
|
||||
cell->unsetPort(it.first);
|
||||
cell->setPort(it.first, port_x);
|
||||
return design_copy;
|
||||
}
|
||||
|
||||
if (!stage2 && (cell->input(it.first) || cell->output(it.first)) && index++ == seed)
|
||||
{
|
||||
log("Trying to expose cell port %s.%s.%s as module port.\n", mod->name.c_str(), cell->name.c_str(), it.first.c_str());
|
||||
RTLIL::Wire *wire = mod->addWire(NEW_ID, port.size());
|
||||
wire->set_bool_attribute("$bugpoint");
|
||||
wire->port_input = cell->input(it.first);
|
||||
wire->port_output = cell->output(it.first);
|
||||
cell->unsetPort(it.first);
|
||||
cell->setPort(it.first, wire);
|
||||
mod->fixup_ports();
|
||||
return design_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
string yosys_cmd = "yosys", script, grep;
|
||||
bool fast = false, clean = false;
|
||||
bool modules = false, ports = false, cells = false, connections = false, has_part = false;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
if (args[argidx] == "-yosys" && argidx + 1 < args.size()) {
|
||||
yosys_cmd = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-script" && argidx + 1 < args.size()) {
|
||||
script = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-grep" && argidx + 1 < args.size()) {
|
||||
grep = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-fast") {
|
||||
fast = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-clean") {
|
||||
clean = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-modules") {
|
||||
modules = true;
|
||||
has_part = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-ports") {
|
||||
ports = true;
|
||||
has_part = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-cells") {
|
||||
cells = true;
|
||||
has_part = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-connections") {
|
||||
connections = true;
|
||||
has_part = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (!has_part)
|
||||
{
|
||||
modules = true;
|
||||
ports = true;
|
||||
cells = true;
|
||||
connections = true;
|
||||
}
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
RTLIL::Design *crashing_design = clean_design(design, clean);
|
||||
if (run_yosys(crashing_design, yosys_cmd, script))
|
||||
log_cmd_error("The provided script file and Yosys binary do not crash on this design!\n");
|
||||
if (!check_logfile(grep))
|
||||
log_cmd_error("The provided grep string is not found in the log file!\n");
|
||||
|
||||
int seed = 0, crashing_seed = seed;
|
||||
bool found_something = false, stage2 = false;
|
||||
while (true)
|
||||
{
|
||||
if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections))
|
||||
{
|
||||
simplified = clean_design(simplified, fast, /*do_delete=*/true);
|
||||
|
||||
bool crashes;
|
||||
if (clean)
|
||||
{
|
||||
RTLIL::Design *testcase = clean_design(simplified);
|
||||
crashes = !run_yosys(testcase, yosys_cmd, script);
|
||||
delete testcase;
|
||||
}
|
||||
else
|
||||
{
|
||||
crashes = !run_yosys(simplified, yosys_cmd, script);
|
||||
}
|
||||
|
||||
if (crashes && check_logfile(grep))
|
||||
{
|
||||
log("Testcase crashes.\n");
|
||||
if (crashing_design != design)
|
||||
delete crashing_design;
|
||||
crashing_design = simplified;
|
||||
crashing_seed = seed;
|
||||
found_something = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Testcase does not crash.\n");
|
||||
delete simplified;
|
||||
seed++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
seed = 0;
|
||||
if (found_something)
|
||||
found_something = false;
|
||||
else
|
||||
{
|
||||
if (!stage2)
|
||||
{
|
||||
log("Demoting introduced module ports.\n");
|
||||
stage2 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Simplifications exhausted.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (crashing_design != design)
|
||||
{
|
||||
Pass::call(design, "design -reset");
|
||||
crashing_design = clean_design(crashing_design, clean, /*do_delete=*/true);
|
||||
for (auto &it : crashing_design->modules_)
|
||||
design->add(it.second->clone());
|
||||
delete crashing_design;
|
||||
}
|
||||
}
|
||||
} BugpointPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -32,7 +32,7 @@ struct ChformalPass : public Pass {
|
|||
log(" chformal [types] [mode] [options] [selection]\n");
|
||||
log("\n");
|
||||
log("Make changes to the formal constraints of the design. The [types] options\n");
|
||||
log("the type of constraint to operate on. If none of the folling options is given,\n");
|
||||
log("the type of constraint to operate on. If none of the following options are given,\n");
|
||||
log("the command will operate on all constraint types:\n");
|
||||
log("\n");
|
||||
log(" -assert $assert cells, representing assert(...) constraints\n");
|
||||
|
@ -59,7 +59,7 @@ struct ChformalPass : public Pass {
|
|||
log(" -assume2assert\n");
|
||||
log(" -live2fair\n");
|
||||
log(" -fair2live\n");
|
||||
log(" change the roles of cells as indicated. this options can be combined\n");
|
||||
log(" change the roles of cells as indicated. these options can be combined\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
|
|
@ -137,7 +137,7 @@ struct ConnectPass : public Pass {
|
|||
if (!set_lhs.empty())
|
||||
{
|
||||
if (!unset_expr.empty() || !port_cell.empty())
|
||||
log_cmd_error("Cant use -set together with -unset and/or -port.\n");
|
||||
log_cmd_error("Can't use -set together with -unset and/or -port.\n");
|
||||
|
||||
RTLIL::SigSpec sig_lhs, sig_rhs;
|
||||
if (!RTLIL::SigSpec::parse_sel(sig_lhs, design, module, set_lhs))
|
||||
|
@ -157,7 +157,7 @@ struct ConnectPass : public Pass {
|
|||
if (!unset_expr.empty())
|
||||
{
|
||||
if (!port_cell.empty() || flag_nounset)
|
||||
log_cmd_error("Cant use -unset together with -port and/or -nounset.\n");
|
||||
log_cmd_error("Can't use -unset together with -port and/or -nounset.\n");
|
||||
|
||||
RTLIL::SigSpec sig;
|
||||
if (!RTLIL::SigSpec::parse_sel(sig, design, module, unset_expr))
|
||||
|
@ -170,7 +170,7 @@ struct ConnectPass : public Pass {
|
|||
if (!port_cell.empty())
|
||||
{
|
||||
if (flag_nounset)
|
||||
log_cmd_error("Cant use -port together with -nounset.\n");
|
||||
log_cmd_error("Can't use -port together with -nounset.\n");
|
||||
|
||||
if (module->cells_.count(RTLIL::escape_id(port_cell)) == 0)
|
||||
log_cmd_error("Can't find cell %s.\n", port_cell.c_str());
|
||||
|
|
|
@ -61,6 +61,42 @@ static std::string derive_name_from_src(const std::string &src, int counter)
|
|||
return stringf("\\%s$%d", src_base.c_str(), counter);
|
||||
}
|
||||
|
||||
static IdString derive_name_from_wire(const RTLIL::Cell &cell)
|
||||
{
|
||||
// Find output
|
||||
const SigSpec *output = nullptr;
|
||||
int num_outputs = 0;
|
||||
for (auto &connection : cell.connections()) {
|
||||
if (cell.output(connection.first)) {
|
||||
output = &connection.second;
|
||||
num_outputs++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_outputs != 1) // Skip cells thad drive multiple outputs
|
||||
return cell.name;
|
||||
|
||||
std::string name = "";
|
||||
for (auto &chunk : output->chunks()) {
|
||||
// Skip cells that drive privately named wires
|
||||
if (!chunk.wire || chunk.wire->name.str()[0] == '$')
|
||||
return cell.name;
|
||||
|
||||
if (name != "")
|
||||
name += "$";
|
||||
|
||||
name += chunk.wire->name.str();
|
||||
if (chunk.wire->width != chunk.width) {
|
||||
name += "[";
|
||||
if (chunk.width != 1)
|
||||
name += std::to_string(chunk.offset + chunk.width) + ":";
|
||||
name += std::to_string(chunk.offset) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
return name + cell.type.str();
|
||||
}
|
||||
|
||||
struct RenamePass : public Pass {
|
||||
RenamePass() : Pass("rename", "rename object in the design") { }
|
||||
void help() YS_OVERRIDE
|
||||
|
@ -77,6 +113,10 @@ struct RenamePass : public Pass {
|
|||
log("Assign names auto-generated from the src attribute to all selected wires and\n");
|
||||
log("cells with private names.\n");
|
||||
log("\n");
|
||||
log(" rename -wire [selection]\n");
|
||||
log("Assign auto-generated names based on the wires they drive to all selected\n");
|
||||
log("cells with private names. Ignores cells driving privatly named wires.\n");
|
||||
log("\n");
|
||||
log(" rename -enumerate [-pattern <pattern>] [selection]\n");
|
||||
log("\n");
|
||||
log("Assign short auto-generated names to all selected wires and cells with private\n");
|
||||
|
@ -98,6 +138,7 @@ struct RenamePass : public Pass {
|
|||
{
|
||||
std::string pattern_prefix = "_", pattern_suffix = "_";
|
||||
bool flag_src = false;
|
||||
bool flag_wire = false;
|
||||
bool flag_enumerate = false;
|
||||
bool flag_hide = false;
|
||||
bool flag_top = false;
|
||||
|
@ -112,6 +153,11 @@ struct RenamePass : public Pass {
|
|||
got_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-wire" && !got_mode) {
|
||||
flag_wire = true;
|
||||
got_mode = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-enumerate" && !got_mode) {
|
||||
flag_enumerate = true;
|
||||
got_mode = true;
|
||||
|
@ -167,6 +213,26 @@ struct RenamePass : public Pass {
|
|||
}
|
||||
}
|
||||
else
|
||||
if (flag_wire)
|
||||
{
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (auto &mod : design->modules_)
|
||||
{
|
||||
RTLIL::Module *module = mod.second;
|
||||
if (!design->selected(module))
|
||||
continue;
|
||||
|
||||
dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
|
||||
for (auto &it : module->cells_) {
|
||||
if (it.first[0] == '$' && design->selected(module, it.second))
|
||||
it.second->name = derive_name_from_wire(*it.second);
|
||||
new_cells[it.second->name] = it.second;
|
||||
}
|
||||
module->cells_.swap(new_cells);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (flag_enumerate)
|
||||
{
|
||||
extra_args(args, argidx, design);
|
||||
|
|
|
@ -987,7 +987,7 @@ struct SelectPass : public Pass {
|
|||
log("list of selected objects.\n");
|
||||
log("\n");
|
||||
log("Note that many commands support an optional [selection] argument that can be\n");
|
||||
log("used to YS_OVERRIDE the global selection for the command. The syntax of this\n");
|
||||
log("used to override the global selection for the command. The syntax of this\n");
|
||||
log("optional argument is identical to the syntax of the <selection> argument\n");
|
||||
log("described here.\n");
|
||||
log("\n");
|
||||
|
|
|
@ -137,7 +137,7 @@ struct SetundefPass : public Pass {
|
|||
log(" replace with $anyconst drivers (for formal)\n");
|
||||
log("\n");
|
||||
log(" -random <seed>\n");
|
||||
log(" replace with random bits using the specified integer als seed\n");
|
||||
log(" replace with random bits using the specified integer as seed\n");
|
||||
log(" value for the random number generator.\n");
|
||||
log("\n");
|
||||
log(" -init\n");
|
||||
|
|
|
@ -623,7 +623,7 @@ struct ShowPass : public Pass {
|
|||
log(" assigned to each unique value of this attribute.\n");
|
||||
log("\n");
|
||||
log(" -width\n");
|
||||
log(" annotate busses with a label indicating the width of the bus.\n");
|
||||
log(" annotate buses with a label indicating the width of the bus.\n");
|
||||
log("\n");
|
||||
log(" -signed\n");
|
||||
log(" mark ports (A, B) that are declared as signed (using the [AB]_SIGNED\n");
|
||||
|
|
|
@ -37,7 +37,7 @@ struct TeePass : public Pass {
|
|||
log("specified logfile(s).\n");
|
||||
log("\n");
|
||||
log(" -q\n");
|
||||
log(" Do not print output to the normal destination (console and/or log file)\n");
|
||||
log(" Do not print output to the normal destination (console and/or log file).\n");
|
||||
log("\n");
|
||||
log(" -o logfile\n");
|
||||
log(" Write output to this file, truncate if exists.\n");
|
||||
|
@ -46,7 +46,7 @@ struct TeePass : public Pass {
|
|||
log(" Write output to this file, append if exists.\n");
|
||||
log("\n");
|
||||
log(" +INT, -INT\n");
|
||||
log(" Add/subract INT from the -v setting for this command.\n");
|
||||
log(" Add/subtract INT from the -v setting for this command.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
|
|
@ -196,13 +196,13 @@ static void detect_fsm(RTLIL::Wire *wire)
|
|||
vector<string> warnings;
|
||||
|
||||
if (is_module_port)
|
||||
warnings.push_back("Forcing fsm recoding on module port might result in larger circuit.\n");
|
||||
warnings.push_back("Forcing FSM recoding on module port might result in larger circuit.\n");
|
||||
|
||||
if (!looks_like_good_state_reg)
|
||||
warnings.push_back("Users of state reg look like fsm recoding might result in larger circuit.\n");
|
||||
warnings.push_back("Users of state reg look like FSM recoding might result in larger circuit.\n");
|
||||
|
||||
if (has_init_attr)
|
||||
warnings.push_back("Init value on fsm state registers are ignored. Possible simulation-synthesis mismatch!");
|
||||
warnings.push_back("Initialization value on FSM state register is ignored. Possible simulation-synthesis mismatch!\n");
|
||||
|
||||
if (!looks_like_state_reg)
|
||||
warnings.push_back("Doesn't look like a proper FSM. Possible simulation-synthesis mismatch!\n");
|
||||
|
@ -236,7 +236,7 @@ static void detect_fsm(RTLIL::Wire *wire)
|
|||
log(" Users of register don't seem to benefit from recoding.\n");
|
||||
|
||||
if (has_init_attr)
|
||||
log(" Register has an initialization value.");
|
||||
log(" Register has an initialization value.\n");
|
||||
|
||||
if (is_self_resetting)
|
||||
log(" Circuit seems to be self-resetting.\n");
|
||||
|
|
|
@ -178,7 +178,7 @@ undef_bit_in_next_state:
|
|||
log_state_in = fsm_data.state_table.at(state_in);
|
||||
|
||||
if (states.count(ce.values_map(ce.assign_map(dff_in)).as_const()) == 0) {
|
||||
log(" transition: %10s %s -> INVALID_STATE(%s) %s <ignored invalid transistion!>%s\n",
|
||||
log(" transition: %10s %s -> INVALID_STATE(%s) %s <ignored invalid transition!>%s\n",
|
||||
log_signal(log_state_in), log_signal(tr.ctrl_in),
|
||||
log_signal(ce.values_map(ce.assign_map(dff_in))), log_signal(tr.ctrl_out),
|
||||
undef_bit_in_next_state_mode ? " SHORTENED" : "");
|
||||
|
@ -194,7 +194,7 @@ undef_bit_in_next_state:
|
|||
log_signal(log_state_in), log_signal(tr.ctrl_in),
|
||||
log_signal(fsm_data.state_table[tr.state_out]), log_signal(tr.ctrl_out));
|
||||
} else {
|
||||
log(" transition: %10s %s -> %10s %s <ignored undef transistion!>\n",
|
||||
log(" transition: %10s %s -> %10s %s <ignored undef transition!>\n",
|
||||
log_signal(log_state_in), log_signal(tr.ctrl_in),
|
||||
log_signal(fsm_data.state_table[tr.state_out]), log_signal(tr.ctrl_out));
|
||||
}
|
||||
|
|
|
@ -543,7 +543,7 @@ struct HierarchyPass : public Pass {
|
|||
log(" an unknown module is used as cell type.\n");
|
||||
log("\n");
|
||||
log(" -simcheck\n");
|
||||
log(" like -check, but also thow an error if blackbox modules are\n");
|
||||
log(" like -check, but also throw an error if blackbox modules are\n");
|
||||
log(" instantiated, and throw an error if the design has no top module\n");
|
||||
log("\n");
|
||||
log(" -purge_lib\n");
|
||||
|
|
|
@ -184,9 +184,6 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
|
|||
mem->parameters["\\OFFSET"] = Const(memory->start_offset);
|
||||
mem->parameters["\\SIZE"] = Const(memory->size);
|
||||
mem->parameters["\\ABITS"] = Const(addr_bits);
|
||||
|
||||
while (GetSize(init_data) > 1 && init_data.bits.back() == State::Sx && init_data.bits[GetSize(init_data)-2] == State::Sx)
|
||||
init_data.bits.pop_back();
|
||||
mem->parameters["\\INIT"] = init_data;
|
||||
|
||||
log_assert(sig_wr_clk.size() == wr_ports);
|
||||
|
|
|
@ -6,12 +6,12 @@ OBJS += passes/opt/opt_reduce.o
|
|||
OBJS += passes/opt/opt_rmdff.o
|
||||
OBJS += passes/opt/opt_clean.o
|
||||
OBJS += passes/opt/opt_expr.o
|
||||
OBJS += passes/opt/opt_lut.o
|
||||
|
||||
ifneq ($(SMALL),1)
|
||||
OBJS += passes/opt/share.o
|
||||
OBJS += passes/opt/wreduce.o
|
||||
OBJS += passes/opt/opt_demorgan.o
|
||||
OBJS += passes/opt/rmports.o
|
||||
OBJS += passes/opt/opt_lut.o
|
||||
endif
|
||||
|
||||
|
|
|
@ -259,6 +259,22 @@ bool is_one_or_minus_one(const Const &value, bool is_signed, bool &is_negative)
|
|||
return last_bit_one;
|
||||
}
|
||||
|
||||
int get_highest_hot_index(RTLIL::SigSpec signal)
|
||||
{
|
||||
for (int i = GetSize(signal) - 1; i >= 0; i--)
|
||||
{
|
||||
if (signal[i] == RTLIL::State::S0)
|
||||
continue;
|
||||
|
||||
if (signal[i] == RTLIL::State::S1)
|
||||
return i;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if the signal has only one bit set, return the index of that bit.
|
||||
// otherwise return -1
|
||||
int get_onehot_bit_index(RTLIL::SigSpec signal)
|
||||
|
@ -1344,119 +1360,140 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
|
|||
}
|
||||
}
|
||||
|
||||
// replace a<0 or a>=0 with the top bit of a
|
||||
// simplify comparisons
|
||||
if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le"))
|
||||
{
|
||||
//used to decide whether the signal needs to be negated
|
||||
bool is_lt = false;
|
||||
IdString cmp_type = cell->type;
|
||||
SigSpec var_sig = cell->getPort("\\A");
|
||||
SigSpec const_sig = cell->getPort("\\B");
|
||||
int var_width = cell->parameters["\\A_WIDTH"].as_int();
|
||||
int const_width = cell->parameters["\\B_WIDTH"].as_int();
|
||||
bool is_signed = cell->getParam("\\A_SIGNED").as_bool();
|
||||
|
||||
//references the variable signal in the comparison
|
||||
RTLIL::SigSpec sigVar;
|
||||
|
||||
//references the constant signal in the comparison
|
||||
RTLIL::SigSpec sigConst;
|
||||
|
||||
// note that this signal must be constant for the optimization
|
||||
// to take place, but it is not checked beforehand.
|
||||
// If new passes are added, this signal must be checked for const-ness
|
||||
|
||||
//width of the variable port
|
||||
int width;
|
||||
int const_width;
|
||||
|
||||
bool var_signed;
|
||||
|
||||
if (cell->type == "$lt" || cell->type == "$ge") {
|
||||
is_lt = cell->type == "$lt" ? 1 : 0;
|
||||
sigVar = cell->getPort("\\A");
|
||||
sigConst = cell->getPort("\\B");
|
||||
width = cell->parameters["\\A_WIDTH"].as_int();
|
||||
const_width = cell->parameters["\\B_WIDTH"].as_int();
|
||||
var_signed = cell->parameters["\\A_SIGNED"].as_bool();
|
||||
} else
|
||||
if (cell->type == "$gt" || cell->type == "$le") {
|
||||
is_lt = cell->type == "$gt" ? 1 : 0;
|
||||
sigVar = cell->getPort("\\B");
|
||||
sigConst = cell->getPort("\\A");
|
||||
width = cell->parameters["\\B_WIDTH"].as_int();
|
||||
const_width = cell->parameters["\\A_WIDTH"].as_int();
|
||||
var_signed = cell->parameters["\\B_SIGNED"].as_bool();
|
||||
} else
|
||||
log_abort();
|
||||
|
||||
// replace a(signed) < 0 with the high bit of a
|
||||
if (sigConst.is_fully_const() && sigConst.is_fully_zero() && var_signed == true)
|
||||
if (!const_sig.is_fully_const())
|
||||
{
|
||||
RTLIL::SigSpec a_prime(RTLIL::State::S0, cell->parameters["\\Y_WIDTH"].as_int());
|
||||
a_prime[0] = sigVar[width - 1];
|
||||
if (is_lt) {
|
||||
log("Replacing %s cell `%s' (implementing X<0) with X[%d]: %s\n",
|
||||
log_id(cell->type), log_id(cell), width-1, log_signal(a_prime));
|
||||
module->connect(cell->getPort("\\Y"), a_prime);
|
||||
module->remove(cell);
|
||||
} else {
|
||||
log("Replacing %s cell `%s' (implementing X>=0) with ~X[%d]: %s\n",
|
||||
log_id(cell->type), log_id(cell), width-1, log_signal(a_prime));
|
||||
module->addNot(NEW_ID, a_prime, cell->getPort("\\Y"));
|
||||
module->remove(cell);
|
||||
}
|
||||
did_something = true;
|
||||
goto next_cell;
|
||||
} else
|
||||
if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false)
|
||||
std::swap(var_sig, const_sig);
|
||||
std::swap(var_width, const_width);
|
||||
if (cmp_type == "$gt")
|
||||
cmp_type = "$lt";
|
||||
else if (cmp_type == "$lt")
|
||||
cmp_type = "$gt";
|
||||
else if (cmp_type == "$ge")
|
||||
cmp_type = "$le";
|
||||
else if (cmp_type == "$le")
|
||||
cmp_type = "$ge";
|
||||
}
|
||||
|
||||
if (const_sig.is_fully_def() && const_sig.is_fully_const())
|
||||
{
|
||||
if (sigConst.is_fully_zero()) {
|
||||
RTLIL::SigSpec a_prime(RTLIL::State::S0, GetSize(cell->getPort("\\Y")));
|
||||
if (is_lt) {
|
||||
log("Replacing %s cell `%s' (implementing unsigned X<0) with constant false.\n",
|
||||
log_id(cell->type), log_id(cell));
|
||||
a_prime[0] = RTLIL::State::S0;
|
||||
} else {
|
||||
log("Replacing %s cell `%s' (implementing unsigned X>=0) with constant true.\n",
|
||||
log_id(cell->type), log_id(cell));
|
||||
a_prime[0] = RTLIL::State::S1;
|
||||
std::string condition, replacement;
|
||||
SigSpec replace_sig(State::S0, GetSize(cell->getPort("\\Y")));
|
||||
bool replace = false;
|
||||
bool remove = false;
|
||||
|
||||
if (!is_signed)
|
||||
{ /* unsigned */
|
||||
if (const_sig.is_fully_zero() && cmp_type == "$lt") {
|
||||
condition = "unsigned X<0";
|
||||
replacement = "constant 0";
|
||||
replace_sig[0] = State::S0;
|
||||
replace = true;
|
||||
}
|
||||
if (const_sig.is_fully_zero() && cmp_type == "$ge") {
|
||||
condition = "unsigned X>=0";
|
||||
replacement = "constant 1";
|
||||
replace_sig[0] = State::S1;
|
||||
replace = true;
|
||||
}
|
||||
if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$gt") {
|
||||
condition = "unsigned X>~0";
|
||||
replacement = "constant 0";
|
||||
replace_sig[0] = State::S0;
|
||||
replace = true;
|
||||
}
|
||||
if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$le") {
|
||||
condition = "unsigned X<=~0";
|
||||
replacement = "constant 1";
|
||||
replace_sig[0] = State::S1;
|
||||
replace = true;
|
||||
}
|
||||
|
||||
int const_bit_hot = get_onehot_bit_index(const_sig);
|
||||
if (const_bit_hot >= 0 && const_bit_hot < var_width)
|
||||
{
|
||||
RTLIL::SigSpec var_high_sig(RTLIL::State::S0, var_width - const_bit_hot);
|
||||
for (int i = const_bit_hot; i < var_width; i++) {
|
||||
var_high_sig[i - const_bit_hot] = var_sig[i];
|
||||
}
|
||||
|
||||
if (cmp_type == "$lt")
|
||||
{
|
||||
condition = stringf("unsigned X<%s", log_signal(const_sig));
|
||||
replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot);
|
||||
module->addLogicNot(NEW_ID, var_high_sig, cell->getPort("\\Y"));
|
||||
remove = true;
|
||||
}
|
||||
if (cmp_type == "$ge")
|
||||
{
|
||||
condition = stringf("unsigned X>=%s", log_signal(const_sig));
|
||||
replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot);
|
||||
module->addReduceOr(NEW_ID, var_high_sig, cell->getPort("\\Y"));
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
int const_bit_set = get_highest_hot_index(const_sig);
|
||||
if(const_bit_set >= var_width)
|
||||
{
|
||||
string cmp_name;
|
||||
if (cmp_type == "$lt" || cmp_type == "$le")
|
||||
{
|
||||
if (cmp_type == "$lt") cmp_name = "<";
|
||||
if (cmp_type == "$le") cmp_name = "<=";
|
||||
condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig));
|
||||
replacement = "constant 1";
|
||||
replace_sig[0] = State::S1;
|
||||
replace = true;
|
||||
}
|
||||
if (cmp_type == "$gt" || cmp_type == "$ge")
|
||||
{
|
||||
if (cmp_type == "$gt") cmp_name = ">";
|
||||
if (cmp_type == "$ge") cmp_name = ">=";
|
||||
condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig));
|
||||
replacement = "constant 0";
|
||||
replace_sig[0] = State::S0;
|
||||
replace = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* signed */
|
||||
if (const_sig.is_fully_zero() && cmp_type == "$lt")
|
||||
{
|
||||
condition = "signed X<0";
|
||||
replacement = stringf("X[%d]", var_width - 1);
|
||||
replace_sig[0] = var_sig[var_width - 1];
|
||||
replace = true;
|
||||
}
|
||||
if (const_sig.is_fully_zero() && cmp_type == "$ge")
|
||||
{
|
||||
condition = "signed X>=0";
|
||||
replacement = stringf("X[%d]", var_width - 1);
|
||||
module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort("\\Y"));
|
||||
remove = true;
|
||||
}
|
||||
module->connect(cell->getPort("\\Y"), a_prime);
|
||||
module->remove(cell);
|
||||
did_something = true;
|
||||
goto next_cell;
|
||||
}
|
||||
|
||||
int const_bit_set = get_onehot_bit_index(sigConst);
|
||||
if (const_bit_set >= 0 && const_bit_set < width) {
|
||||
int bit_set = const_bit_set;
|
||||
RTLIL::SigSpec a_prime(RTLIL::State::S0, width - bit_set);
|
||||
for (int i = bit_set; i < width; i++) {
|
||||
a_prime[i - bit_set] = sigVar[i];
|
||||
}
|
||||
if (is_lt) {
|
||||
log("Replacing %s cell `%s' (implementing unsigned X<%s) with !X[%d:%d]: %s.\n",
|
||||
log_id(cell->type), log_id(cell), log_signal(sigConst), width - 1, bit_set, log_signal(a_prime));
|
||||
module->addLogicNot(NEW_ID, a_prime, cell->getPort("\\Y"));
|
||||
} else {
|
||||
log("Replacing %s cell `%s' (implementing unsigned X>=%s) with |X[%d:%d]: %s.\n",
|
||||
log_id(cell->type), log_id(cell), log_signal(sigConst), width - 1, bit_set, log_signal(a_prime));
|
||||
module->addReduceOr(NEW_ID, a_prime, cell->getPort("\\Y"));
|
||||
}
|
||||
if (replace || remove)
|
||||
{
|
||||
log("Replacing %s cell `%s' (implementing %s) with %s.\n",
|
||||
log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str());
|
||||
if (replace)
|
||||
module->connect(cell->getPort("\\Y"), replace_sig);
|
||||
module->remove(cell);
|
||||
did_something = true;
|
||||
goto next_cell;
|
||||
}
|
||||
else if(const_bit_set >= width && const_bit_set >= 0){
|
||||
RTLIL::SigSpec a_prime(RTLIL::State::S0, 1);
|
||||
if(is_lt){
|
||||
a_prime[0] = RTLIL::State::S1;
|
||||
log("Replacing %s cell `%s' (implementing unsigned X[%d:0] < %s[%d:0]) with constant 0.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1);
|
||||
}
|
||||
else{
|
||||
log("Replacing %s cell `%s' (implementing unsigned X[%d:0]>= %s[%d:0]) with constant 1.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1);
|
||||
}
|
||||
module->connect(cell->getPort("\\Y"), a_prime);
|
||||
module->remove(cell);
|
||||
did_something = true;
|
||||
goto next_cell;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1477,7 +1514,7 @@ struct OptExprPass : public Pass {
|
|||
log(" opt_expr [options] [selection]\n");
|
||||
log("\n");
|
||||
log("This pass performs const folding on internal cell types with constant inputs.\n");
|
||||
log("It also performs some simple expression rewritring.\n");
|
||||
log("It also performs some simple expression rewriting.\n");
|
||||
log("\n");
|
||||
log(" -mux_undef\n");
|
||||
log(" remove 'undef' inputs from $mux, $pmux and $_MUX_ cells\n");
|
||||
|
|
|
@ -36,7 +36,7 @@ struct OptLutWorker
|
|||
dict<RTLIL::Cell*, pool<RTLIL::Cell*>> luts_dlogics;
|
||||
dict<RTLIL::Cell*, pool<int>> luts_dlogic_inputs;
|
||||
|
||||
int combined_count = 0;
|
||||
int eliminated_count = 0, combined_count = 0;
|
||||
|
||||
bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
|
||||
{
|
||||
|
@ -133,7 +133,7 @@ struct OptLutWorker
|
|||
// Second, make sure that the connection to dedicated logic is legal. If it is not legal,
|
||||
// it means one of the two things:
|
||||
// * The connection is spurious. I.e. this is dedicated logic that will be packed
|
||||
// with some other LUT, and it just happens to be conected to this LUT as well.
|
||||
// with some other LUT, and it just happens to be connected to this LUT as well.
|
||||
// * The connection is illegal.
|
||||
// In either of these cases, we don't need to concern ourselves with preserving the connection
|
||||
// between this LUT and this dedicated logic cell.
|
||||
|
@ -188,7 +188,7 @@ struct OptLutWorker
|
|||
show_stats_by_arity();
|
||||
|
||||
log("\n");
|
||||
log("Combining LUTs.\n");
|
||||
log("Eliminating LUTs.\n");
|
||||
pool<RTLIL::Cell*> worklist = luts;
|
||||
while (worklist.size())
|
||||
{
|
||||
|
@ -198,6 +198,106 @@ struct OptLutWorker
|
|||
break;
|
||||
}
|
||||
|
||||
auto lut = worklist.pop();
|
||||
SigSpec lut_input = sigmap(lut->getPort("\\A"));
|
||||
pool<int> &lut_dlogic_inputs = luts_dlogic_inputs[lut];
|
||||
|
||||
vector<SigBit> lut_inputs;
|
||||
for (auto &bit : lut_input)
|
||||
{
|
||||
if (bit.wire)
|
||||
lut_inputs.push_back(sigmap(bit));
|
||||
}
|
||||
|
||||
bool const0_match = true;
|
||||
bool const1_match = true;
|
||||
vector<bool> input_matches;
|
||||
for (size_t i = 0; i < lut_inputs.size(); i++)
|
||||
input_matches.push_back(true);
|
||||
|
||||
for (int eval = 0; eval < 1 << lut_inputs.size(); eval++)
|
||||
{
|
||||
dict<SigBit, bool> eval_inputs;
|
||||
for (size_t i = 0; i < lut_inputs.size(); i++)
|
||||
eval_inputs[lut_inputs[i]] = (eval >> i) & 1;
|
||||
bool value = evaluate_lut(lut, eval_inputs);
|
||||
if (value != 0)
|
||||
const0_match = false;
|
||||
if (value != 1)
|
||||
const1_match = false;
|
||||
for (size_t i = 0; i < lut_inputs.size(); i++)
|
||||
{
|
||||
if (value != eval_inputs[lut_inputs[i]])
|
||||
input_matches[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
int input_match = -1;
|
||||
for (size_t i = 0; i < lut_inputs.size(); i++)
|
||||
if (input_matches[i])
|
||||
input_match = i;
|
||||
|
||||
if (const0_match || const1_match || input_match != -1)
|
||||
{
|
||||
log("Found redundant cell %s.%s.\n", log_id(module), log_id(lut));
|
||||
|
||||
SigBit value;
|
||||
if (const0_match)
|
||||
{
|
||||
log(" Cell evaluates constant 0.\n");
|
||||
value = State::S0;
|
||||
}
|
||||
if (const1_match)
|
||||
{
|
||||
log(" Cell evaluates constant 1.\n");
|
||||
value = State::S1;
|
||||
}
|
||||
if (input_match != -1) {
|
||||
log(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match]));
|
||||
value = lut_inputs[input_match];
|
||||
}
|
||||
|
||||
if (lut_dlogic_inputs.size())
|
||||
{
|
||||
log(" Not eliminating cell (connected to dedicated logic).\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
SigSpec lut_output = lut->getPort("\\Y");
|
||||
for (auto &port : index.query_ports(lut_output))
|
||||
{
|
||||
if (port.cell != lut && luts.count(port.cell))
|
||||
worklist.insert(port.cell);
|
||||
}
|
||||
|
||||
module->connect(lut_output, value);
|
||||
sigmap.add(lut_output, value);
|
||||
|
||||
module->remove(lut);
|
||||
luts.erase(lut);
|
||||
luts_arity.erase(lut);
|
||||
luts_dlogics.erase(lut);
|
||||
luts_dlogic_inputs.erase(lut);
|
||||
|
||||
eliminated_count++;
|
||||
if (limit > 0)
|
||||
limit--;
|
||||
}
|
||||
}
|
||||
}
|
||||
show_stats_by_arity();
|
||||
|
||||
log("\n");
|
||||
log("Combining LUTs.\n");
|
||||
worklist = luts;
|
||||
while (worklist.size())
|
||||
{
|
||||
if (limit == 0)
|
||||
{
|
||||
log("Limit reached.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
auto lutA = worklist.pop();
|
||||
SigSpec lutA_input = sigmap(lutA->getPort("\\A"));
|
||||
SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]);
|
||||
|
@ -487,16 +587,20 @@ struct OptLutPass : public Pass {
|
|||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
int total_count = 0;
|
||||
int eliminated_count = 0, combined_count = 0;
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
OptLutWorker worker(dlogic, module, limit - total_count);
|
||||
total_count += worker.combined_count;
|
||||
OptLutWorker worker(dlogic, module, limit - eliminated_count - combined_count);
|
||||
eliminated_count += worker.eliminated_count;
|
||||
combined_count += worker.combined_count;
|
||||
}
|
||||
if (total_count)
|
||||
if (eliminated_count)
|
||||
design->scratchpad_set_bool("opt.did_something", true);
|
||||
if (combined_count)
|
||||
design->scratchpad_set_bool("opt.did_something", true);
|
||||
log("\n");
|
||||
log("Combined %d LUTs.\n", total_count);
|
||||
log("Eliminated %d LUTs.\n", eliminated_count);
|
||||
log("Combined %d LUTs.\n", combined_count);
|
||||
}
|
||||
} OptLutPass;
|
||||
|
||||
|
|
|
@ -710,8 +710,12 @@ struct ShareWorker
|
|||
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1);
|
||||
RTLIL::SigSpec addr1 = c1->getPort("\\ADDR");
|
||||
RTLIL::SigSpec addr2 = c2->getPort("\\ADDR");
|
||||
if (addr1 != addr2)
|
||||
supercell->setPort("\\ADDR", module->Mux(NEW_ID, addr2, addr1, act));
|
||||
if (GetSize(addr1) < GetSize(addr2))
|
||||
addr1.extend_u0(GetSize(addr2));
|
||||
else
|
||||
addr2.extend_u0(GetSize(addr1));
|
||||
supercell->setPort("\\ADDR", addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1);
|
||||
supercell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr1));
|
||||
supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort("\\DATA"), c2->getPort("\\DATA")));
|
||||
supercell_aux.insert(supercell);
|
||||
return supercell;
|
||||
|
|
|
@ -235,8 +235,11 @@ struct WreduceWorker
|
|||
} else {
|
||||
while (GetSize(sig) > 0)
|
||||
{
|
||||
auto info = mi.query(sig[GetSize(sig)-1]);
|
||||
auto bit = sig[GetSize(sig)-1];
|
||||
if (keep_bits.count(bit))
|
||||
break;
|
||||
|
||||
auto info = mi.query(bit);
|
||||
if (info->is_output || GetSize(info->ports) > 1)
|
||||
break;
|
||||
|
||||
|
|
|
@ -77,18 +77,42 @@ void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did
|
|||
}
|
||||
else
|
||||
{
|
||||
bool all_cases_are_empty = true;
|
||||
for (auto cs : sw->cases) {
|
||||
if (cs->actions.size() != 0 || cs->switches.size() != 0)
|
||||
all_cases_are_empty = false;
|
||||
bool all_fully_def = true;
|
||||
for (auto cs : sw->cases)
|
||||
{
|
||||
if (max_depth != 0)
|
||||
proc_clean_case(cs, did_something, count, max_depth-1);
|
||||
int size = 0;
|
||||
for (auto cmp : cs->compare)
|
||||
{
|
||||
size += cmp.size();
|
||||
if (!cmp.is_fully_def())
|
||||
all_fully_def = false;
|
||||
}
|
||||
if (sw->signal.size() != size)
|
||||
all_fully_def = false;
|
||||
}
|
||||
if (all_cases_are_empty) {
|
||||
did_something = true;
|
||||
for (auto cs : sw->cases)
|
||||
delete cs;
|
||||
sw->cases.clear();
|
||||
if (all_fully_def)
|
||||
{
|
||||
for (auto cs = sw->cases.begin(); cs != sw->cases.end();)
|
||||
{
|
||||
if ((*cs)->empty())
|
||||
{
|
||||
did_something = true;
|
||||
delete *cs;
|
||||
cs = sw->cases.erase(cs);
|
||||
}
|
||||
else ++cs;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!sw->cases.empty() && sw->cases.back()->empty())
|
||||
{
|
||||
did_something = true;
|
||||
delete sw->cases.back();
|
||||
sw->cases.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +130,7 @@ void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int m
|
|||
}
|
||||
for (size_t i = 0; i < cs->switches.size(); i++) {
|
||||
RTLIL::SwitchRule *sw = cs->switches[i];
|
||||
if (sw->cases.size() == 0) {
|
||||
if (sw->empty()) {
|
||||
cs->switches.erase(cs->switches.begin() + (i--));
|
||||
did_something = true;
|
||||
delete sw;
|
||||
|
|
|
@ -36,6 +36,7 @@ OBJS += passes/techmap/attrmvcp.o
|
|||
OBJS += passes/techmap/attrmap.o
|
||||
OBJS += passes/techmap/zinit.o
|
||||
OBJS += passes/techmap/dff2dffs.o
|
||||
OBJS += passes/techmap/flowmap.o
|
||||
endif
|
||||
|
||||
GENFILES += passes/techmap/techmap.inc
|
||||
|
|
|
@ -43,18 +43,37 @@ struct DffinitPass : public Pass {
|
|||
log(" initial value of 1 or 0. (multi-bit values are not supported in this\n");
|
||||
log(" mode.)\n");
|
||||
log("\n");
|
||||
log(" -strinit <string for high> <string for low> \n");
|
||||
log(" use string values in the command line to represent a single-bit\n");
|
||||
log(" initial value of 1 or 0. (multi-bit values are not supported in this\n");
|
||||
log(" mode.)\n");
|
||||
log("\n");
|
||||
log(" -noreinit\n");
|
||||
log(" fail if the FF cell has already a defined initial value set in other\n");
|
||||
log(" passes and the initial value of the net it drives is not equal to\n");
|
||||
log(" the already defined initial value.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing DFFINIT pass (set INIT param on FF cells).\n");
|
||||
|
||||
dict<IdString, dict<IdString, IdString>> ff_types;
|
||||
bool highlow_mode = false;
|
||||
bool highlow_mode = false, noreinit = false;
|
||||
std::string high_string, low_string;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-highlow") {
|
||||
highlow_mode = true;
|
||||
high_string = "high";
|
||||
low_string = "low";
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-strinit" && argidx+2 < args.size()) {
|
||||
highlow_mode = true;
|
||||
high_string = args[++argidx];
|
||||
low_string = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-ff" && argidx+3 < args.size()) {
|
||||
|
@ -64,6 +83,10 @@ struct DffinitPass : public Pass {
|
|||
ff_types[cell_name][output_port] = init_param;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-noreinit") {
|
||||
noreinit = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -112,6 +135,10 @@ struct DffinitPass : public Pass {
|
|||
continue;
|
||||
while (GetSize(value.bits) <= i)
|
||||
value.bits.push_back(State::S0);
|
||||
if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i]))
|
||||
log_error("Trying to assign a different init value for %s.%s.%s which technically "
|
||||
"have a conflicted init value.\n",
|
||||
log_id(module), log_id(cell), log_id(it.second));
|
||||
value.bits[i] = init_bits.at(sig[i]);
|
||||
cleanup_bits.insert(sig[i]);
|
||||
}
|
||||
|
@ -121,9 +148,9 @@ struct DffinitPass : public Pass {
|
|||
log_error("Multi-bit init value for %s.%s.%s is incompatible with -highlow mode.\n",
|
||||
log_id(module), log_id(cell), log_id(it.second));
|
||||
if (value[0] == State::S1)
|
||||
value = Const("high");
|
||||
value = Const(high_string);
|
||||
else
|
||||
value = Const("low");
|
||||
value = Const(low_string);
|
||||
}
|
||||
|
||||
log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,22 @@
|
|||
// Exact reproduction of Figure 2(a) from 10.1109/43.273754.
|
||||
module top(...);
|
||||
input a,b,c,d,e,f;
|
||||
wire nA = b&c;
|
||||
wire A = !nA;
|
||||
wire nB = c|d;
|
||||
wire B = !nB;
|
||||
wire nC = e&f;
|
||||
wire C = !nC;
|
||||
wire D = A|B;
|
||||
wire E = a&D;
|
||||
wire nF = D&C;
|
||||
wire F = !nF;
|
||||
wire nG = F|B;
|
||||
wire G = !nG;
|
||||
wire H = a&F;
|
||||
wire I = E|G;
|
||||
wire J = G&C;
|
||||
wire np = H&I;
|
||||
output p = !np;
|
||||
output q = A|J;
|
||||
endmodule
|
|
@ -0,0 +1,16 @@
|
|||
// Like flow.v, but results in a network identical to Figure 2(b).
|
||||
module top(...);
|
||||
input a,b,c,d,e,f;
|
||||
wire A = b&c;
|
||||
wire B = c|d;
|
||||
wire C = e&f;
|
||||
wire D = A|B;
|
||||
wire E = a&D;
|
||||
wire F = D&C;
|
||||
wire G = F|B;
|
||||
wire H = a&F;
|
||||
wire I = E|G;
|
||||
wire J = G&C;
|
||||
output p = H&I;
|
||||
output q = A|J;
|
||||
endmodule
|
|
@ -0,0 +1,11 @@
|
|||
// Exact reproduction of Figure 3(a) from 10.1109/92.285741.
|
||||
module top(...);
|
||||
input a,b,c,d,e,f,g,h;
|
||||
wire x = !(c|d);
|
||||
wire y = !(e&f);
|
||||
wire u = !(a&b);
|
||||
wire v = !(x|y);
|
||||
wire w = !(g&h);
|
||||
output s = !(u|v);
|
||||
output t = !(v|w);
|
||||
endmodule
|
|
@ -0,0 +1,11 @@
|
|||
// Like pack1.v, but results in a simpler network.
|
||||
module top(...);
|
||||
input a,b,c,d,e,f,g,h;
|
||||
wire x = c|d;
|
||||
wire y = e&f;
|
||||
wire u = a&b;
|
||||
wire v = x|y;
|
||||
wire w = g&h;
|
||||
output s = u|v;
|
||||
output t = v|w;
|
||||
endmodule
|
|
@ -0,0 +1,15 @@
|
|||
// Exact reproduction of Figure 4(a) from 10.1109/92.285741.
|
||||
module top(...);
|
||||
(* $flowmap_level=1 *) input a;
|
||||
(* $flowmap_level=1 *) input b;
|
||||
(* $flowmap_level=2 *) input c;
|
||||
(* $flowmap_level=1 *) input d;
|
||||
(* $flowmap_level=3 *) input e;
|
||||
(* $flowmap_level=1 *) input f;
|
||||
wire u = !(a&b);
|
||||
wire w = !(c|d);
|
||||
wire v = !(u|w);
|
||||
wire n0 = !(w&e);
|
||||
wire n1 = !(n0|f);
|
||||
output n2 = !(v&n1);
|
||||
endmodule
|
|
@ -0,0 +1,15 @@
|
|||
// Like pack2.v, but results in a simpler network.
|
||||
module top(...);
|
||||
(* $flowmap_level=1 *) input a;
|
||||
(* $flowmap_level=1 *) input b;
|
||||
(* $flowmap_level=2 *) input c;
|
||||
(* $flowmap_level=1 *) input d;
|
||||
(* $flowmap_level=3 *) input e;
|
||||
(* $flowmap_level=1 *) input f;
|
||||
wire u = a&b;
|
||||
wire w = c|d;
|
||||
wire v = u|w;
|
||||
wire n0 = w&e;
|
||||
wire n1 = n0|f;
|
||||
output n2 = v&n1;
|
||||
endmodule
|
|
@ -0,0 +1,15 @@
|
|||
// Exact reproduction of Figure 5(a) (bottom) from 10.1109/92.285741.
|
||||
module top(...);
|
||||
input a,b,c,d,e,f,g,h,i,j;
|
||||
wire x = !(a&b);
|
||||
wire y = !(c|d);
|
||||
wire z = !(e|f);
|
||||
wire n0 = !(g&h);
|
||||
wire n1 = !(i|j);
|
||||
wire w = !(x&y);
|
||||
wire n2 = !(z&n0);
|
||||
wire n3 = !(n0|n1);
|
||||
wire n4 = !(n2|n3);
|
||||
wire v = !(w|n5);
|
||||
output u = !(w&v);
|
||||
endmodule
|
|
@ -0,0 +1,15 @@
|
|||
// Like pack2.v, but results in a simpler network.
|
||||
module top(...);
|
||||
input a,b,c,d,e,f,g,h,i,j;
|
||||
wire x = a&b;
|
||||
wire y = c|d;
|
||||
wire z = e|f;
|
||||
wire n0 = g&h;
|
||||
wire n1 = i|j;
|
||||
wire w = x&y;
|
||||
wire n2 = z&n0;
|
||||
wire n3 = n0|n1;
|
||||
wire n4 = n2|n3;
|
||||
wire v = w|n5;
|
||||
output u = w&v;
|
||||
endmodule
|
|
@ -32,7 +32,7 @@ endmodule
|
|||
// > end buffers <
|
||||
|
||||
// > Look-Up table <
|
||||
// > VT: I still think Achronix folks would have choosen a better \
|
||||
// > VT: I still think Achronix folks would have chosen a better \
|
||||
// > logic architecture.
|
||||
// LUT Map
|
||||
module \$lut (A, Y);
|
||||
|
@ -43,30 +43,30 @@ module \$lut (A, Y);
|
|||
generate
|
||||
if (WIDTH == 1) begin
|
||||
// VT: This is not consistent and ACE will complain: assign Y = ~A[0];
|
||||
LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_
|
||||
LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_
|
||||
(.dout(Y), .din0(A[0]), .din1(1'b0), .din2(1'b0), .din3(1'b0));
|
||||
end else
|
||||
if (WIDTH == 2) begin
|
||||
LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_
|
||||
LUT4 #(.lut_function({4{LUT}})) _TECHMAP_REPLACE_
|
||||
(.dout(Y), .din0(A[0]), .din1(A[1]), .din2(1'b0), .din3(1'b0));
|
||||
end else
|
||||
if(WIDTH == 3) begin
|
||||
LUT4 #(.lut_function({2{LUT}})) _TECHMAP_REPLACE_
|
||||
LUT4 #(.lut_function({2{LUT}})) _TECHMAP_REPLACE_
|
||||
(.dout(Y), .din0(A[0]), .din1(A[1]), .din2(A[2]), .din3(1'b0));
|
||||
end else
|
||||
if(WIDTH == 4) begin
|
||||
LUT4 #(.lut_function(LUT)) _TECHMAP_REPLACE_
|
||||
LUT4 #(.lut_function(LUT)) _TECHMAP_REPLACE_
|
||||
(.dout(Y), .din0(A[0]), .din1(A[1]), .din2(A[2]), .din3(A[3]));
|
||||
end else
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
endgenerate
|
||||
endmodule
|
||||
endmodule
|
||||
// > end LUT <
|
||||
|
||||
// > Flops <
|
||||
// DFF flop
|
||||
module \$_DFF_P_ (input D, C, output Q);
|
||||
DFF _TECHMAP_REPLACE_
|
||||
DFF _TECHMAP_REPLACE_
|
||||
(.q(Q), .d(D), .ck(C));
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ reg [1:0] s1;
|
|||
end
|
||||
endfunction
|
||||
|
||||
always @(dataa_w or datab_w or datac_w or datad_w or cin_w) begin
|
||||
always @(dataa_w or datab_w or datac_w or datad_w) begin
|
||||
combout_rt = lut_data(lut_function, dataa_w, datab_w,
|
||||
datac_w, datad_w);
|
||||
end
|
||||
|
|
|
@ -95,8 +95,8 @@ struct SynthAchronixPass : public ScriptPass {
|
|||
run_to = args[argidx].substr(pos+1);
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-flatten") {
|
||||
flatten = true;
|
||||
if (args[argidx] == "-noflatten") {
|
||||
flatten = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-retime") {
|
||||
|
@ -108,7 +108,7 @@ struct SynthAchronixPass : public ScriptPass {
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_ACHRONIX pass.\n");
|
||||
log_push();
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
|
||||
OBJS += techlibs/anlogic/synth_anlogic.o
|
||||
OBJS += techlibs/anlogic/anlogic_eqn.o
|
||||
OBJS += techlibs/anlogic/anlogic_determine_init.o
|
||||
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_sim.v))
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/eagle_bb.v))
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/drams.txt))
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/drams_map.v))
|
||||
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/dram_init_16x4.vh))
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
|
||||
*
|
||||
* 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/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct AnlogicDetermineInitPass : public Pass {
|
||||
AnlogicDetermineInitPass() : Pass("anlogic_determine_init", "Anlogic: Determine the init value of cells") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
log("\n");
|
||||
log(" anlogic_determine_init [selection]\n");
|
||||
log("\n");
|
||||
log("Determine the init value of cells that doesn't allow unknown init value.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
Const determine_init(Const init)
|
||||
{
|
||||
for (int i = 0; i < GetSize(init); i++) {
|
||||
if (init[i] != State::S0 && init[i] != State::S1)
|
||||
init[i] = State::S0;
|
||||
}
|
||||
|
||||
return init;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing ANLOGIC_DETERMINE_INIT pass (determine init value for cells).\n");
|
||||
|
||||
extra_args(args, args.size(), design);
|
||||
|
||||
size_t cnt = 0;
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
if (cell->type == "\\EG_LOGIC_DRAM16X4")
|
||||
{
|
||||
cell->setParam("\\INIT_D0", determine_init(cell->getParam("\\INIT_D0")));
|
||||
cell->setParam("\\INIT_D1", determine_init(cell->getParam("\\INIT_D1")));
|
||||
cell->setParam("\\INIT_D2", determine_init(cell->getParam("\\INIT_D2")));
|
||||
cell->setParam("\\INIT_D3", determine_init(cell->getParam("\\INIT_D3")));
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
log_header(design, "Updated %lu cells with determined init value.\n", cnt);
|
||||
}
|
||||
} AnlogicDetermineInitPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -1,19 +1,31 @@
|
|||
module \$_DFF_N_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(1'b0)); endmodule
|
||||
module \$_DFF_P_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(1'b0)); endmodule
|
||||
module \$_DFF_N_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(1'b0)); endmodule
|
||||
module \$_DFF_P_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(1'b0)); endmodule
|
||||
|
||||
module \$_DFFE_NN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_NN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
|
||||
module \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'bx), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
|
||||
|
||||
module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b0), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
|
||||
module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET(1'b1), .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
|
||||
|
||||
module \$_DLATCH_N_ (E, D, Q);
|
||||
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
|
||||
input E, D;
|
||||
output Q = !E ? D : Q;
|
||||
endmodule
|
||||
|
||||
module \$_DLATCH_P_ (E, D, Q);
|
||||
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
|
||||
input E, D;
|
||||
output Q = E ? D : Q;
|
||||
endmodule
|
||||
|
||||
`ifndef NO_LUT
|
||||
module \$lut (A, Y);
|
||||
|
|
|
@ -17,7 +17,7 @@ module AL_MAP_LUT1 (
|
|||
);
|
||||
parameter [1:0] INIT = 2'h0;
|
||||
parameter EQN = "(A)";
|
||||
assign Y = INIT >> A;
|
||||
assign o = INIT >> a;
|
||||
endmodule
|
||||
|
||||
module AL_MAP_LUT2 (
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
.INIT_D0({INIT[15*4+0], INIT[14*4+0], INIT[13*4+0], INIT[12*4+0],
|
||||
INIT[11*4+0], INIT[10*4+0], INIT[9*4+0], INIT[8*4+0],
|
||||
INIT[7*4+0], INIT[6*4+0], INIT[5*4+0], INIT[4*4+0],
|
||||
INIT[3*4+0], INIT[2*4+0], INIT[1*4+0], INIT[0*4+0]}),
|
||||
.INIT_D1({INIT[15*4+1], INIT[14*4+1], INIT[13*4+1], INIT[12*4+1],
|
||||
INIT[11*4+1], INIT[10*4+1], INIT[9*4+1], INIT[8*4+1],
|
||||
INIT[7*4+1], INIT[6*4+1], INIT[5*4+1], INIT[4*4+1],
|
||||
INIT[3*4+1], INIT[2*4+1], INIT[1*4+1], INIT[0*4+1]}),
|
||||
.INIT_D2({INIT[15*4+2], INIT[14*4+2], INIT[13*4+2], INIT[12*4+2],
|
||||
INIT[11*4+2], INIT[10*4+2], INIT[9*4+2], INIT[8*4+2],
|
||||
INIT[7*4+2], INIT[6*4+2], INIT[5*4+2], INIT[4*4+2],
|
||||
INIT[3*4+2], INIT[2*4+2], INIT[1*4+2], INIT[0*4+2]}),
|
||||
.INIT_D3({INIT[15*4+3], INIT[14*4+3], INIT[13*4+3], INIT[12*4+3],
|
||||
INIT[11*4+3], INIT[10*4+3], INIT[9*4+3], INIT[8*4+3],
|
||||
INIT[7*4+3], INIT[6*4+3], INIT[5*4+3], INIT[4*4+3],
|
||||
INIT[3*4+3], INIT[2*4+3], INIT[1*4+3], INIT[0*4+3]})
|
|
@ -1,7 +1,7 @@
|
|||
bram $__ANLOGIC_DRAM16X4
|
||||
init 0
|
||||
init 1
|
||||
abits 4
|
||||
dbits 2
|
||||
dbits 4
|
||||
groups 2
|
||||
ports 1 1
|
||||
wrmode 0 1
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module \$__ANLOGIC_DRAM16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
||||
parameter [63:0]INIT = 64'bx;
|
||||
input CLK1;
|
||||
|
||||
input [3:0] A1ADDR;
|
||||
|
@ -8,7 +9,9 @@ module \$__ANLOGIC_DRAM16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
|||
input [3:0] B1DATA;
|
||||
input B1EN;
|
||||
|
||||
EG_LOGIC_DRAM16X4 _TECHMAP_REPLACE_ (
|
||||
EG_LOGIC_DRAM16X4 #(
|
||||
`include "dram_init_16x4.vh"
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.di(B1DATA),
|
||||
.waddr(B1ADDR),
|
||||
.wclk(CLK1),
|
||||
|
|
|
@ -119,7 +119,7 @@ struct SynthAnlogicPass : public ScriptPass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_ANLOGIC pass.\n");
|
||||
log_push();
|
||||
|
@ -154,6 +154,7 @@ struct SynthAnlogicPass : public ScriptPass
|
|||
{
|
||||
run("memory_bram -rules +/anlogic/drams.txt");
|
||||
run("techmap -map +/anlogic/drams_map.v");
|
||||
run("anlogic_determine_init");
|
||||
}
|
||||
|
||||
if (check_label("fine"))
|
||||
|
@ -170,13 +171,14 @@ struct SynthAnlogicPass : public ScriptPass
|
|||
{
|
||||
run("dffsr2dff");
|
||||
run("techmap -D NO_LUT -map +/anlogic/cells_map.v");
|
||||
run("dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit");
|
||||
run("opt_expr -mux_undef");
|
||||
run("simplemap");
|
||||
}
|
||||
|
||||
if (check_label("map_luts"))
|
||||
{
|
||||
run("abc -lut 6");
|
||||
run("abc -lut 4:6");
|
||||
run("clean");
|
||||
}
|
||||
|
||||
|
|
|
@ -26,5 +26,5 @@ $(eval $(call add_share_file,share,techlibs/common/pmux2mux.v))
|
|||
$(eval $(call add_share_file,share,techlibs/common/adff2dff.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/dff2ff.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/gate2lut.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/cmp2lut.v))
|
||||
$(eval $(call add_share_file,share,techlibs/common/cells.lib))
|
||||
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
// Certain arithmetic operations between a signal of width n and a constant can be directly mapped
|
||||
// to a single k-LUT (where n <= k). This is preferable to normal alumacc techmapping process
|
||||
// because for many targets, arithmetic techmapping creates hard logic (such as carry cells) which often
|
||||
// cannot be optimized further.
|
||||
//
|
||||
// TODO: Currently, only comparisons with 1-bit output are mapped. Potentially, all arithmetic cells
|
||||
// with n <= k inputs should be techmapped in this way, because this shortens the critical path
|
||||
// from n to 1 by avoiding carry chains.
|
||||
|
||||
(* techmap_celltype = "$eq $ne $lt $le $gt $ge" *)
|
||||
module _90_lut_cmp_ (A, B, Y);
|
||||
|
||||
parameter A_SIGNED = 0;
|
||||
parameter B_SIGNED = 0;
|
||||
parameter A_WIDTH = 0;
|
||||
parameter B_WIDTH = 0;
|
||||
parameter Y_WIDTH = 0;
|
||||
|
||||
input [A_WIDTH-1:0] A;
|
||||
input [B_WIDTH-1:0] B;
|
||||
output [Y_WIDTH-1:0] Y;
|
||||
|
||||
parameter _TECHMAP_CELLTYPE_ = "";
|
||||
|
||||
parameter _TECHMAP_CONSTMSK_A_ = 0;
|
||||
parameter _TECHMAP_CONSTVAL_A_ = 0;
|
||||
parameter _TECHMAP_CONSTMSK_B_ = 0;
|
||||
parameter _TECHMAP_CONSTVAL_B_ = 0;
|
||||
|
||||
function automatic integer gen_lut;
|
||||
input integer width;
|
||||
input integer operation;
|
||||
input integer swap;
|
||||
input integer sign;
|
||||
input integer operand;
|
||||
integer n, i_var, i_cst, lhs, rhs, o_bit;
|
||||
begin
|
||||
gen_lut = width'b0;
|
||||
for (n = 0; n < (1 << width); n++) begin
|
||||
if (sign)
|
||||
i_var = n[width-1:0];
|
||||
else
|
||||
i_var = n;
|
||||
i_cst = operand;
|
||||
if (swap) begin
|
||||
lhs = i_cst;
|
||||
rhs = i_var;
|
||||
end else begin
|
||||
lhs = i_var;
|
||||
rhs = i_cst;
|
||||
end
|
||||
if (operation == 0)
|
||||
o_bit = (lhs < rhs);
|
||||
if (operation == 1)
|
||||
o_bit = (lhs <= rhs);
|
||||
if (operation == 2)
|
||||
o_bit = (lhs > rhs);
|
||||
if (operation == 3)
|
||||
o_bit = (lhs >= rhs);
|
||||
if (operation == 4)
|
||||
o_bit = (lhs == rhs);
|
||||
if (operation == 5)
|
||||
o_bit = (lhs != rhs);
|
||||
gen_lut = gen_lut | (o_bit << n);
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
generate
|
||||
if (_TECHMAP_CELLTYPE_ == "$lt")
|
||||
localparam operation = 0;
|
||||
if (_TECHMAP_CELLTYPE_ == "$le")
|
||||
localparam operation = 1;
|
||||
if (_TECHMAP_CELLTYPE_ == "$gt")
|
||||
localparam operation = 2;
|
||||
if (_TECHMAP_CELLTYPE_ == "$ge")
|
||||
localparam operation = 3;
|
||||
if (_TECHMAP_CELLTYPE_ == "$eq")
|
||||
localparam operation = 4;
|
||||
if (_TECHMAP_CELLTYPE_ == "$ne")
|
||||
localparam operation = 5;
|
||||
|
||||
if (A_WIDTH > `LUT_WIDTH || B_WIDTH > `LUT_WIDTH || Y_WIDTH != 1)
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
else if (&_TECHMAP_CONSTMSK_B_)
|
||||
\$lut #(
|
||||
.WIDTH(A_WIDTH),
|
||||
.LUT({ gen_lut(A_WIDTH, operation, 0, A_SIGNED && B_SIGNED, _TECHMAP_CONSTVAL_B_) })
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.A(A),
|
||||
.Y(Y)
|
||||
);
|
||||
else if (&_TECHMAP_CONSTMSK_A_)
|
||||
\$lut #(
|
||||
.WIDTH(B_WIDTH),
|
||||
.LUT({ gen_lut(B_WIDTH, operation, 1, A_SIGNED && B_SIGNED, _TECHMAP_CONSTVAL_A_) })
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.A(B),
|
||||
.Y(Y)
|
||||
);
|
||||
else
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
endgenerate
|
||||
|
||||
endmodule
|
|
@ -153,7 +153,7 @@ struct PrepPass : public ScriptPass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing PREP pass.\n");
|
||||
log_push();
|
||||
|
|
|
@ -51,6 +51,9 @@ struct SynthPass : public ScriptPass
|
|||
log(" -encfile <file>\n");
|
||||
log(" passed to 'fsm_recode' via 'fsm'\n");
|
||||
log("\n");
|
||||
log(" -lut <k>\n");
|
||||
log(" perform synthesis for a k-LUT architecture.\n");
|
||||
log("\n");
|
||||
log(" -nofsm\n");
|
||||
log(" do not run FSM optimization\n");
|
||||
log("\n");
|
||||
|
@ -80,6 +83,7 @@ struct SynthPass : public ScriptPass
|
|||
|
||||
string top_module, fsm_opts, memory_opts;
|
||||
bool autotop, flatten, noalumacc, nofsm, noabc, noshare;
|
||||
int lut;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
|
@ -89,6 +93,7 @@ struct SynthPass : public ScriptPass
|
|||
|
||||
autotop = false;
|
||||
flatten = false;
|
||||
lut = 0;
|
||||
noalumacc = false;
|
||||
nofsm = false;
|
||||
noabc = false;
|
||||
|
@ -130,6 +135,10 @@ struct SynthPass : public ScriptPass
|
|||
flatten = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-lut") {
|
||||
lut = atoi(args[++argidx].c_str());
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nofsm") {
|
||||
nofsm = true;
|
||||
continue;
|
||||
|
@ -155,7 +164,7 @@ struct SynthPass : public ScriptPass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH pass.\n");
|
||||
log_push();
|
||||
|
@ -186,19 +195,23 @@ struct SynthPass : public ScriptPass
|
|||
{
|
||||
run("proc");
|
||||
if (help_mode || flatten)
|
||||
run("flatten", "(if -flatten)");
|
||||
run("flatten", " (if -flatten)");
|
||||
run("opt_expr");
|
||||
run("opt_clean");
|
||||
run("check");
|
||||
run("opt");
|
||||
run("wreduce");
|
||||
if (help_mode)
|
||||
run("techmap -map +/cmp2lut.v", " (if -lut)");
|
||||
else
|
||||
run(stringf("techmap -map +/cmp2lut.v -D LUT_WIDTH=%d", lut));
|
||||
if (!noalumacc)
|
||||
run("alumacc");
|
||||
run("alumacc", " (unless -noalumacc)");
|
||||
if (!noshare)
|
||||
run("share");
|
||||
run("share", " (unless -noshare)");
|
||||
run("opt");
|
||||
if (!nofsm)
|
||||
run("fsm" + fsm_opts);
|
||||
run("fsm" + fsm_opts, " (unless -nofsm)");
|
||||
run("opt -fast");
|
||||
run("memory -nomap" + memory_opts);
|
||||
run("opt_clean");
|
||||
|
@ -210,12 +223,33 @@ struct SynthPass : public ScriptPass
|
|||
run("memory_map");
|
||||
run("opt -full");
|
||||
run("techmap");
|
||||
if (help_mode)
|
||||
{
|
||||
run("techmap -map +/gate2lut.v", "(if -noabc and -lut)");
|
||||
run("clean; opt_lut", " (if -noabc and -lut)");
|
||||
}
|
||||
else if (noabc && lut)
|
||||
{
|
||||
run(stringf("techmap -map +/gate2lut.v -D LUT_WIDTH=%d", lut));
|
||||
run("clean; opt_lut");
|
||||
}
|
||||
run("opt -fast");
|
||||
|
||||
if (!noabc) {
|
||||
#ifdef YOSYS_ENABLE_ABC
|
||||
run("abc -fast");
|
||||
run("opt -fast");
|
||||
if (help_mode)
|
||||
{
|
||||
run("abc -fast", " (unless -noabc, unless -lut)");
|
||||
run("abc -fast -lut k", "(unless -noabc, if -lut)");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lut)
|
||||
run(stringf("abc -fast -lut %d", lut));
|
||||
else
|
||||
run("abc -fast");
|
||||
}
|
||||
run("opt -fast", " (unless -noabc)");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ struct SynthCoolrunner2Pass : public ScriptPass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_COOLRUNNER2 pass.\n");
|
||||
log_push();
|
||||
|
@ -129,7 +129,7 @@ struct SynthCoolrunner2Pass : public ScriptPass
|
|||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||
}
|
||||
|
||||
if (check_label("flatten", "(unless -noflatten)") && flatten)
|
||||
if (flatten && check_label("flatten", "(unless -noflatten)"))
|
||||
{
|
||||
run("proc");
|
||||
run("flatten");
|
||||
|
|
|
@ -117,7 +117,7 @@ struct SynthEasicPass : public ScriptPass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_EASIC pass.\n");
|
||||
log_push();
|
||||
|
|
|
@ -34,11 +34,11 @@ techlibs/ecp5/bram_conn_4.vh: techlibs/ecp5/brams_connect.mk
|
|||
techlibs/ecp5/bram_conn_9.vh: techlibs/ecp5/brams_connect.mk
|
||||
techlibs/ecp5/bram_conn_18.vh: techlibs/ecp5/brams_connect.mk
|
||||
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_init_1_2_4.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_init_9_18_36.vh))
|
||||
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_init_1_2_4.vh))
|
||||
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_init_9_18_36.vh))
|
||||
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_1.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_2.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_4.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_9.vh))
|
||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_18.vh))
|
||||
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_1.vh))
|
||||
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_2.vh))
|
||||
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_4.vh))
|
||||
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_9.vh))
|
||||
$(eval $(call add_gen_share_file,share/ecp5,techlibs/ecp5/bram_conn_18.vh))
|
||||
|
|
|
@ -484,7 +484,7 @@ module DCUA(
|
|||
parameter D_XGE_MODE = "0b0";
|
||||
|
||||
// These parameters don't do anything but are
|
||||
// needed for compatability with Diamond
|
||||
// needed for compatibility with Diamond
|
||||
parameter D_TX_MAX_RATE = "2.5";
|
||||
parameter D_RX_MAX_RATE = "2.5";
|
||||
parameter CH0_TXAMPLITUDE = "0d1300";
|
||||
|
|
|
@ -189,7 +189,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_ECP5 pass.\n");
|
||||
log_push();
|
||||
|
|
|
@ -52,6 +52,9 @@ struct SynthGowinPass : public ScriptPass
|
|||
log(" -nobram\n");
|
||||
log(" do not use BRAM cells in output netlist\n");
|
||||
log("\n");
|
||||
log(" -noflatten\n");
|
||||
log(" do not flatten design before synthesis\n");
|
||||
log("\n");
|
||||
log(" -retime\n");
|
||||
log(" run 'abc' with -dff option\n");
|
||||
log("\n");
|
||||
|
@ -62,14 +65,15 @@ struct SynthGowinPass : public ScriptPass
|
|||
}
|
||||
|
||||
string top_opt, vout_file;
|
||||
bool retime, nobram;
|
||||
bool retime, flatten, nobram;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
top_opt = "-auto-top";
|
||||
vout_file = "";
|
||||
retime = false;
|
||||
nobram = true;
|
||||
flatten = true;
|
||||
nobram = true;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
@ -104,12 +108,16 @@ struct SynthGowinPass : public ScriptPass
|
|||
nobram = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-noflatten") {
|
||||
flatten = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_GOWIN pass.\n");
|
||||
log_push();
|
||||
|
@ -127,7 +135,7 @@ struct SynthGowinPass : public ScriptPass
|
|||
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
|
||||
}
|
||||
|
||||
if (check_label("flatten") && check_label("flatten", "(unless -noflatten)"))
|
||||
if (flatten && check_label("flatten", "(unless -noflatten)"))
|
||||
{
|
||||
run("proc");
|
||||
run("flatten");
|
||||
|
|
|
@ -120,7 +120,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
if (part != "SLG46140V" && part != "SLG46620V" && part != "SLG46621V")
|
||||
log_cmd_error("Invalid part name: '%s'\n", part.c_str());
|
||||
|
|
|
@ -198,7 +198,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_ICE40 pass.\n");
|
||||
log_push();
|
||||
|
@ -226,7 +226,7 @@ struct SynthIce40Pass : public ScriptPass
|
|||
|
||||
if (check_label("coarse"))
|
||||
{
|
||||
run("synth -run coarse");
|
||||
run("synth -lut 4 -run coarse");
|
||||
}
|
||||
|
||||
if (!nobram && check_label("bram", "(skip if -nobram)"))
|
||||
|
|
|
@ -54,7 +54,7 @@ module cyclonev_lcell_comb
|
|||
// Internal variables
|
||||
// Sub mask for fragmented LUTs
|
||||
wire [15:0] mask_a, mask_b, mask_c, mask_d;
|
||||
// Independant output for fragmented LUTs
|
||||
// Independent output for fragmented LUTs
|
||||
wire output_0, output_1, output_2, output_3;
|
||||
// Extended mode uses mux to define the output
|
||||
wire mux_0, mux_1;
|
||||
|
|
|
@ -131,8 +131,8 @@ struct SynthIntelPass : public ScriptPass {
|
|||
nobram = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-flatten") {
|
||||
flatten = true;
|
||||
if (args[argidx] == "-noflatten") {
|
||||
flatten = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-retime") {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
OBJS += techlibs/sf2/synth_sf2.o
|
||||
OBJS += techlibs/sf2/sf2_iobs.o
|
||||
|
||||
$(eval $(call add_share_file,share/sf2,techlibs/sf2/arith_map.v))
|
||||
$(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_map.v))
|
||||
|
|
|
@ -73,3 +73,24 @@ module CFG4 (
|
|||
parameter [15:0] INIT = 16'h0;
|
||||
assign Y = INIT >> {D, C, B, A};
|
||||
endmodule
|
||||
|
||||
module CLKBUF (
|
||||
input PAD,
|
||||
output Y
|
||||
);
|
||||
assign Y = PAD;
|
||||
endmodule
|
||||
|
||||
module INBUF (
|
||||
input PAD,
|
||||
output Y
|
||||
);
|
||||
assign Y = PAD;
|
||||
endmodule
|
||||
|
||||
module OUTBUF (
|
||||
input D,
|
||||
output PAD
|
||||
);
|
||||
assign PAD = D;
|
||||
endmodule
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||
*
|
||||
* 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/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct Sf2IobsPass : public Pass {
|
||||
Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" sf2_iobs [options] [selection]\n");
|
||||
log("\n");
|
||||
log("Add SF2 I/O buffers to top module IOs as needed.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
// if (args[argidx] == "-singleton") {
|
||||
// singleton_mode = true;
|
||||
// continue;
|
||||
// }
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
Module *module = design->top_module();
|
||||
|
||||
if (module == nullptr)
|
||||
log_cmd_error("No top module found.\n");
|
||||
|
||||
SigMap sigmap(module);
|
||||
|
||||
pool<SigBit> clk_bits;
|
||||
pool<SigBit> handled_io_bits;
|
||||
dict<SigBit, SigBit> rewrite_bits;
|
||||
vector<pair<Cell*, SigBit>> pad_bits;
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type == "\\SLE") {
|
||||
for (auto bit : sigmap(cell->getPort("\\CLK")))
|
||||
clk_bits.insert(bit);
|
||||
}
|
||||
if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) {
|
||||
for (auto bit : sigmap(cell->getPort("\\PAD")))
|
||||
handled_io_bits.insert(bit);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto wire : vector<Wire*>(module->wires()))
|
||||
{
|
||||
if (!wire->port_input && !wire->port_output)
|
||||
continue;
|
||||
|
||||
for (int index = 0; index < GetSize(wire); index++)
|
||||
{
|
||||
SigBit bit(wire, index);
|
||||
SigBit canonical_bit = sigmap(bit);
|
||||
|
||||
if (handled_io_bits.count(canonical_bit))
|
||||
continue;
|
||||
|
||||
if (wire->port_input && wire->port_output)
|
||||
log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit));
|
||||
|
||||
IdString buf_type, buf_port;
|
||||
|
||||
if (wire->port_output) {
|
||||
buf_type = "\\OUTBUF";
|
||||
buf_port = "\\D";
|
||||
} else if (clk_bits.count(canonical_bit)) {
|
||||
buf_type = "\\CLKBUF";
|
||||
buf_port = "\\Y";
|
||||
} else {
|
||||
buf_type = "\\INBUF";
|
||||
buf_port = "\\Y";
|
||||
}
|
||||
|
||||
Cell *c = module->addCell(NEW_ID, buf_type);
|
||||
SigBit new_bit = module->addWire(NEW_ID);
|
||||
c->setPort(buf_port, new_bit);
|
||||
pad_bits.push_back(make_pair(c, bit));
|
||||
rewrite_bits[canonical_bit] = new_bit;
|
||||
|
||||
log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
|
||||
}
|
||||
}
|
||||
|
||||
auto rewrite_function = [&](SigSpec &s) {
|
||||
for (auto &bit : s) {
|
||||
SigBit canonical_bit = sigmap(bit);
|
||||
if (rewrite_bits.count(canonical_bit))
|
||||
bit = rewrite_bits.at(canonical_bit);
|
||||
}
|
||||
};
|
||||
|
||||
module->rewrite_sigspecs(rewrite_function);
|
||||
|
||||
for (auto &it : pad_bits)
|
||||
it.first->setPort("\\PAD", it.second);
|
||||
}
|
||||
} Sf2IobsPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -44,6 +44,10 @@ struct SynthSf2Pass : public ScriptPass
|
|||
log(" write the design to the specified EDIF file. writing of an output file\n");
|
||||
log(" is omitted if this parameter is not specified.\n");
|
||||
log("\n");
|
||||
log(" -vlog <file>\n");
|
||||
log(" write the design to the specified Verilog file. writing of an output file\n");
|
||||
log(" is omitted if this parameter is not specified.\n");
|
||||
log("\n");
|
||||
log(" -json <file>\n");
|
||||
log(" write the design to the specified JSON file. writing of an output file\n");
|
||||
log(" is omitted if this parameter is not specified.\n");
|
||||
|
@ -56,6 +60,9 @@ struct SynthSf2Pass : public ScriptPass
|
|||
log(" -noflatten\n");
|
||||
log(" do not flatten design before synthesis\n");
|
||||
log("\n");
|
||||
log(" -noiobs\n");
|
||||
log(" run synthesis in \"block mode\", i.e. do not insert IO buffers\n");
|
||||
log("\n");
|
||||
log(" -retime\n");
|
||||
log(" run 'abc' with -dff option\n");
|
||||
log("\n");
|
||||
|
@ -65,16 +72,18 @@ struct SynthSf2Pass : public ScriptPass
|
|||
log("\n");
|
||||
}
|
||||
|
||||
string top_opt, edif_file, json_file;
|
||||
bool flatten, retime;
|
||||
string top_opt, edif_file, vlog_file, json_file;
|
||||
bool flatten, retime, iobs;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
top_opt = "-auto-top";
|
||||
edif_file = "";
|
||||
vlog_file = "";
|
||||
json_file = "";
|
||||
flatten = true;
|
||||
retime = false;
|
||||
iobs = true;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
@ -93,6 +102,10 @@ struct SynthSf2Pass : public ScriptPass
|
|||
edif_file = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-vlog" && argidx+1 < args.size()) {
|
||||
vlog_file = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-json" && argidx+1 < args.size()) {
|
||||
json_file = args[++argidx];
|
||||
continue;
|
||||
|
@ -113,12 +126,16 @@ struct SynthSf2Pass : public ScriptPass
|
|||
retime = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-noiobs") {
|
||||
iobs = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
log_header(design, "Executing SYNTH_SF2 pass.\n");
|
||||
log_push();
|
||||
|
@ -182,6 +199,13 @@ struct SynthSf2Pass : public ScriptPass
|
|||
run("clean");
|
||||
}
|
||||
|
||||
if (check_label("map_iobs"))
|
||||
{
|
||||
if (iobs || help_mode)
|
||||
run("sf2_iobs", "(unless -noiobs)");
|
||||
run("clean");
|
||||
}
|
||||
|
||||
if (check_label("check"))
|
||||
{
|
||||
run("hierarchy -check");
|
||||
|
@ -192,7 +216,13 @@ struct SynthSf2Pass : public ScriptPass
|
|||
if (check_label("edif"))
|
||||
{
|
||||
if (!edif_file.empty() || help_mode)
|
||||
run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
|
||||
run(stringf("write_edif -gndvccy %s", help_mode ? "<file-name>" : edif_file.c_str()));
|
||||
}
|
||||
|
||||
if (check_label("vlog"))
|
||||
{
|
||||
if (!vlog_file.empty() || help_mode)
|
||||
run(stringf("write_verilog %s", help_mode ? "<file-name>" : vlog_file.c_str()));
|
||||
}
|
||||
|
||||
if (check_label("json"))
|
||||
|
|
|
@ -178,7 +178,7 @@ struct SynthXilinxPass : public Pass
|
|||
extra_args(args, argidx, design);
|
||||
|
||||
if (!design->full_selection())
|
||||
log_cmd_error("This comannd only operates on fully selected designs!\n");
|
||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
||||
|
||||
bool active = run_from.empty();
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
module misc1 (a,b,c,d,y);
|
||||
input a, b,c,d;
|
||||
output y;
|
||||
|
||||
wire net1,net2,net3;
|
||||
|
||||
supply1 vdd;
|
||||
supply0 vss;
|
||||
|
||||
// y = !((a+b+c).d)
|
||||
|
||||
pmos p1 (vdd,net1,a);
|
||||
pmos p2 (net1,net2,b);
|
||||
pmos p3 (net2,y,c);
|
||||
pmos p4 (vdd,y,d);
|
||||
|
||||
nmos n1 (vss,net3,a);
|
||||
nmos n2 (vss,net3,b);
|
||||
nmos n3 (vss,net3,c);
|
||||
nmos n4 (net3,y,d);
|
||||
|
||||
endmodule
|
|
@ -1,22 +0,0 @@
|
|||
//-----------------------------------------------------
|
||||
// Design Name : mux21_switch
|
||||
// File Name : mux21_switch.v
|
||||
// Function : 2:1 Mux using Switch Primitives
|
||||
// Coder : Deepak Kumar Tala
|
||||
//-----------------------------------------------------
|
||||
module mux21_switch (out, ctrl, in1, in2);
|
||||
|
||||
output out;
|
||||
input ctrl, in1, in2;
|
||||
wire w;
|
||||
|
||||
supply1 power;
|
||||
supply0 ground;
|
||||
|
||||
pmos N1 (w, power, ctrl);
|
||||
nmos N2 (w, ground, ctrl);
|
||||
|
||||
cmos C1 (out, in1, w, ctrl);
|
||||
cmos C2 (out, in2, ctrl, w);
|
||||
|
||||
endmodule
|
|
@ -1,14 +0,0 @@
|
|||
module nand_switch(a,b,out);
|
||||
input a,b;
|
||||
output out;
|
||||
|
||||
supply0 vss;
|
||||
supply1 vdd;
|
||||
wire net1;
|
||||
|
||||
pmos p1 (vdd,out,a);
|
||||
pmos p2 (vdd,out,b);
|
||||
nmos n1 (vss,net1,a);
|
||||
nmos n2 (net1,out,b);
|
||||
|
||||
endmodule
|
|
@ -1,11 +0,0 @@
|
|||
module t_gate_switch (L,R,nC,C);
|
||||
inout L;
|
||||
inout R;
|
||||
input nC;
|
||||
input C;
|
||||
|
||||
//Syntax: keyword unique_name (drain. source, gate);
|
||||
pmos p1 (L,R,nC);
|
||||
nmos p2 (L,R,C);
|
||||
|
||||
endmodule
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue