Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jim Lawson 2019-02-11 12:43:46 -08:00
commit 311396860b
109 changed files with 3480 additions and 414 deletions

View File

@ -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)

View File

@ -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`.

View File

@ -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";

0
backends/btor/test_cells.sh Executable file → Normal file
View File

View File

@ -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");
}

View File

@ -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");

View File

@ -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

View File

@ -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)

View File

@ -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])

View File

@ -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";
}

View File

@ -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));

3
examples/igloo2/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/netlist.edn
/netlist.vm
/proj

View File

@ -0,0 +1 @@
# Add placement constraints here

View File

@ -0,0 +1 @@
# Add timing constraints here

23
examples/igloo2/example.v Normal file
View File

@ -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

View File

@ -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

4
examples/igloo2/runme.sh Normal file
View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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));

View File

@ -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
===============================================================

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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 ;

View File

@ -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
}

View File

@ -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;

View File

@ -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;
};

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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}

View File

@ -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

View File

@ -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

369
passes/cmds/bugpoint.cc Normal file
View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -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);

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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

View File

@ -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");

View File

@ -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));
}

View File

@ -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");

View File

@ -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);

View File

@ -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

View File

@ -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");

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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),

1613
passes/techmap/flowmap.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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))

View File

@ -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

View File

@ -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);

View File

@ -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 (

View File

@ -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]})

View File

@ -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

View File

@ -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),

View File

@ -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");
}

View File

@ -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))

105
techlibs/common/cmp2lut.v Normal file
View File

@ -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

View File

@ -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();

View File

@ -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
}
}

View File

@ -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");

View File

@ -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();

View File

@ -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))

View File

@ -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";

View File

@ -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();

View File

@ -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");

View File

@ -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());

View File

@ -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)"))

View File

@ -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;

View File

@ -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") {

View File

@ -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))

View File

@ -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

130
techlibs/sf2/sf2_iobs.cc Normal file
View File

@ -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

View File

@ -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"))

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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