use patched yosys

pull/1/head
Sebastien Bourdeauducq 2019-03-25 10:12:18 +08:00
parent 602ccc0f47
commit 0f512c762b
3 changed files with 480 additions and 1 deletions

View File

@ -1,6 +1,8 @@
{ pkgs ? import <nixpkgs> {}}:
rec {
nmigen = pkgs.callPackage ./nmigen.nix {};
yosys = pkgs.callPackage ./yosys.nix {};
symbiyosys = pkgs.symbiyosys.override { inherit yosys; };
nmigen = pkgs.callPackage ./nmigen.nix { inherit yosys; };
jtagtap = pkgs.callPackage ./jtagtap.nix { inherit nmigen; };
minerva = pkgs.callPackage ./minerva.nix { inherit nmigen; inherit jtagtap; };
heavycomps = pkgs.callPackage ./heavycomps.nix { inherit nmigen; };

78
yosys.nix Normal file
View File

@ -0,0 +1,78 @@
{ stdenv, fetchFromGitHub
, pkgconfig, bison, flex
, tcl, readline, libffi, python3
, protobuf
}:
with builtins;
stdenv.mkDerivation rec {
name = "yosys-${version}";
version = "2019.03.25hx";
srcs = [
(fetchFromGitHub {
owner = "yosyshq";
repo = "yosys";
rev = "ccfa2fe01cffcc4d23bc989e558bd33addfea58e";
sha256 = "05raqky4l2na8nyim51g8fzv49mg5f3p64lpdr7slxg74s270zry";
name = "yosys";
})
# NOTE: the version of abc used here is synchronized with
# the one in the yosys Makefile of the version above;
# keep them the same for quality purposes.
(fetchFromGitHub {
owner = "berkeley-abc";
repo = "abc";
rev = "2ddc57d8760d94e86699be39a628178cff8154f8";
sha256 = "0da7nnnnl9cq2r7s301xgdc8nlr6hqmqpvd9zn4b58m125sp0scl";
name = "yosys-abc";
})
];
sourceRoot = "yosys";
enableParallelBuilding = true;
nativeBuildInputs = [ pkgconfig ];
buildInputs = [ tcl readline libffi python3 bison flex protobuf ];
makeFlags = [ "ENABLE_PROTOBUF=1" ];
patchPhase = ''
patch -p1 < ${./yosys_726.patch}
substituteInPlace ../yosys-abc/Makefile \
--replace 'CC := gcc' ""
substituteInPlace ./Makefile \
--replace 'CXX = clang' "" \
--replace 'ABCMKARGS = CC="$(CXX)"' 'ABCMKARGS =' \
--replace 'echo UNKNOWN' 'echo ${substring 0 10 (elemAt srcs 0).rev}'
'';
preBuild = ''
chmod -R u+w ../yosys-abc
ln -s ../yosys-abc abc
make config-${if stdenv.cc.isClang or false then "clang" else "gcc"}
echo 'ABCREV := default' >> Makefile.conf
makeFlags="PREFIX=$out $makeFlags"
# we have to do this ourselves for some reason...
(cd misc && ${protobuf}/bin/protoc --cpp_out ../backends/protobuf/ ./yosys.proto)
'';
meta = {
description = "Framework for RTL synthesis tools";
longDescription = ''
Yosys is a framework for RTL synthesis tools. It currently has
extensive Verilog-2005 support and provides a basic set of
synthesis algorithms for various application domains.
Yosys can be adapted to perform any synthesis job by combining
the existing passes (algorithms) using synthesis scripts and
adding additional passes as needed by extending the yosys C++
code base.
'';
homepage = http://www.clifford.at/yosys/;
license = stdenv.lib.licenses.isc;
maintainers = with stdenv.lib.maintainers; [ shell thoughtpolice ];
platforms = stdenv.lib.platforms.unix;
};
}

399
yosys_726.patch Normal file
View File

@ -0,0 +1,399 @@
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 83d83f48..ef6f102c 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -25,6 +25,7 @@
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include "kernel/sigtools.h"
+#include "kernel/modtools.h"
#include <string>
#include <sstream>
#include <set>
@@ -33,15 +34,17 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit;
+bool verbose, norename, noattr, attr2comment, noexpr, nodec, noinline, nohex, nostr, defparam, decimal, siminit;
int auto_name_counter, auto_name_offset, auto_name_digits;
std::map<RTLIL::IdString, int> auto_name_map;
std::set<RTLIL::IdString> reg_wires, reg_ct;
+std::map<RTLIL::Wire*, int> proc_consumed_wires;
std::string auto_prefix;
RTLIL::Module *active_module;
dict<RTLIL::SigBit, RTLIL::State> active_initdata;
SigMap active_sigmap;
+ModIndex active_modindex;
void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
{
@@ -183,6 +186,72 @@ bool is_reg_wire(RTLIL::SigSpec sig, std::string &reg_name)
return true;
}
+bool can_inline_cell_expr(RTLIL::Cell *cell)
+{
+ static pool<IdString> inlinable_cells = {
+ "$not", "$pos", "$neg",
+ "$and", "$or", "$xor", "$xnor",
+ "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool",
+ "$shl", "$shr", "$sshl", "$sshr",
+ "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt",
+ "$add", "$sub", "$mul", "$div", "$mod", "$pow",
+ "$logic_not", "$logic_and", "$logic_or",
+ "$mux"
+ };
+
+ if (noinline)
+ return false;
+
+ if (!inlinable_cells.count(cell->type))
+ return false;
+
+ const RTLIL::SigSpec &output = cell->getPort("\\Y");
+ if (!output.is_wire())
+ return false;
+
+ RTLIL::Wire *output_wire = output.as_wire();
+ if (output_wire->port_id || (!noattr && output_wire->attributes.size()))
+ return false;
+
+ pool<ModIndex::PortInfo> ports = active_modindex.query_ports(output[0]);
+ if (proc_consumed_wires[output_wire] == 1 && ports.size() == 1)
+ return true;
+
+ if (proc_consumed_wires[output_wire] == 0 && ports.size() == 2)
+ {
+ auto port1 = ports.pop();
+ auto port2 = ports.pop();
+ return port1.cell->getPort(port1.port).size() ==
+ port2.cell->getPort(port2.port).size();
+ }
+
+ return false;
+}
+
+bool can_inline_wire(RTLIL::Wire *wire)
+{
+ if (noinline)
+ return false;
+
+ RTLIL::SigSpec wire_spec = RTLIL::SigSpec(wire);
+ if (wire_spec.empty())
+ return false;
+
+ pool<ModIndex::PortInfo> ports = active_modindex.query_ports(wire_spec[0]);
+ if (ports.size() > 2)
+ return false;
+
+ for (auto &port_info : ports)
+ {
+ if (port_info.cell->name[0] == '$' && port_info.port == "\\Y")
+ {
+ if (can_inline_cell_expr(port_info.cell))
+ return true;
+ }
+ }
+ return false;
+}
+
void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool no_decimal = false, bool set_signed = false, bool escape_comment = false)
{
if (width < 0)
@@ -313,13 +382,29 @@ void dump_reg_init(std::ostream &f, SigSpec sig)
}
}
+bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell, bool do_inline);
+
void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decimal = false)
{
if (chunk.wire == NULL) {
dump_const(f, chunk.data, chunk.width, chunk.offset, no_decimal);
} else {
if (chunk.width == chunk.wire->width && chunk.offset == 0) {
- f << stringf("%s", id(chunk.wire->name).c_str());
+ if (can_inline_wire(chunk.wire))
+ {
+ f << "(";
+ pool<ModIndex::PortInfo> ports = active_modindex.query_ports(SigSpec(chunk)[0]);
+ for (auto &port_info : ports)
+ {
+ if (port_info.port == "\\Y")
+ dump_cell_expr(f, "", port_info.cell, true);
+ }
+ f << ")";
+ }
+ else
+ {
+ f << stringf("%s", id(chunk.wire->name).c_str());
+ }
} else if (chunk.width == 1) {
if (chunk.wire->upto)
f << stringf("%s[%d]", id(chunk.wire->name).c_str(), (chunk.wire->width - chunk.offset - 1) + chunk.wire->start_offset);
@@ -372,6 +457,9 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString,
void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
{
+ if (can_inline_wire(wire))
+ return;
+
dump_attributes(f, indent, wire->attributes);
#if 0
if (wire->port_input && !wire->port_output)
@@ -464,30 +552,54 @@ no_special_reg_name:
}
}
-void dump_cell_expr_uniop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op)
+void dump_cell_expr_uniop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op, bool do_inline)
{
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, cell->getPort("\\Y"));
- f << stringf(" = %s ", op.c_str());
+ if (!do_inline)
+ {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, cell->getPort("\\Y"));
+ f << stringf(" = ");
+ }
+ f << stringf("%s ", op.c_str());
dump_attributes(f, "", cell->attributes, ' ');
dump_cell_expr_port(f, cell, "A", true);
- f << stringf(";\n");
+ if (!do_inline)
+ {
+ f << stringf(";\n");
+ }
}
-void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op)
+void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell, std::string op, bool do_inline)
{
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, cell->getPort("\\Y"));
- f << stringf(" = ");
+ if (!do_inline)
+ {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, cell->getPort("\\Y"));
+ f << stringf(" = ");
+ }
+ else
+ {
+ f << stringf("(");
+ }
dump_cell_expr_port(f, cell, "A", true);
f << stringf(" %s ", op.c_str());
dump_attributes(f, "", cell->attributes, ' ');
dump_cell_expr_port(f, cell, "B", true);
- f << stringf(";\n");
+ if (!do_inline)
+ {
+ f << stringf(";\n");
+ }
+ else
+ {
+ f << stringf(")");
+ }
}
-bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
+bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell, bool do_inline)
{
+ if (can_inline_cell_expr(cell) && !do_inline)
+ return true;
+
if (cell->type == "$_NOT_") {
f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort("\\Y"));
@@ -658,9 +770,9 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
}
#define HANDLE_UNIOP(_type, _operator) \
- if (cell->type ==_type) { dump_cell_expr_uniop(f, indent, cell, _operator); return true; }
+ if (cell->type ==_type) { dump_cell_expr_uniop(f, indent, cell, _operator, do_inline); return true; }
#define HANDLE_BINOP(_type, _operator) \
- if (cell->type ==_type) { dump_cell_expr_binop(f, indent, cell, _operator); return true; }
+ if (cell->type ==_type) { dump_cell_expr_binop(f, indent, cell, _operator, do_inline); return true; }
HANDLE_UNIOP("$not", "~")
HANDLE_UNIOP("$pos", "+")
@@ -756,16 +868,30 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
if (cell->type == "$mux")
{
- f << stringf("%s" "assign ", indent.c_str());
- dump_sigspec(f, cell->getPort("\\Y"));
- f << stringf(" = ");
+ if (!do_inline)
+ {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, cell->getPort("\\Y"));
+ f << stringf(" = ");
+ }
+ else
+ {
+ f << stringf("(");
+ }
dump_sigspec(f, cell->getPort("\\S"));
f << stringf(" ? ");
dump_attributes(f, "", cell->attributes, ' ');
dump_sigspec(f, cell->getPort("\\B"));
f << stringf(" : ");
dump_sigspec(f, cell->getPort("\\A"));
- f << stringf(";\n");
+ if (!do_inline)
+ {
+ f << stringf(";\n");
+ }
+ else
+ {
+ f << stringf(")");
+ }
return true;
}
@@ -1243,7 +1369,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
{
if (cell->type[0] == '$' && !noexpr) {
- if (dump_cell_expr(f, indent, cell))
+ if (dump_cell_expr(f, indent, cell, false))
return;
}
@@ -1400,25 +1526,42 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw
void case_body_find_regs(RTLIL::CaseRule *cs)
{
for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it)
- for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
- case_body_find_regs(*it2);
+ {
+ for (auto &c : (*it)->signal.chunks())
+ if (c.wire != NULL && c.offset == 0 && c.width == c.wire->width)
+ proc_consumed_wires[c.wire]++;
+ for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++)
+ case_body_find_regs(*it2);
+ }
- for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) {
+ for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it)
+ {
for (auto &c : it->first.chunks())
+ {
if (c.wire != NULL)
reg_wires.insert(c.wire->name);
+ for (auto &c : it->second.chunks())
+ if (c.wire != NULL && c.offset == 0 && c.width == c.wire->width)
+ proc_consumed_wires[c.wire]++;
+ }
}
}
-void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, bool find_regs = false)
+void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, bool sweep = false)
{
- if (find_regs) {
+ if (sweep) {
case_body_find_regs(&proc->root_case);
for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it)
- for (auto it2 = (*it)->actions.begin(); it2 != (*it)->actions.end(); it2++) {
- for (auto &c : it2->first.chunks())
- if (c.wire != NULL)
- reg_wires.insert(c.wire->name);
+ {
+ for (auto it2 = (*it)->actions.begin(); it2 != (*it)->actions.end(); it2++)
+ {
+ for (auto &c : it2->first.chunks())
+ if (c.wire != NULL)
+ reg_wires.insert(c.wire->name);
+ for (auto &c : it2->second.chunks())
+ if (c.wire != NULL && c.offset == 0 && c.width == c.wire->width)
+ proc_consumed_wires[c.wire]++;
+ }
}
return;
}
@@ -1487,9 +1630,11 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
{
reg_wires.clear();
+ proc_consumed_wires.clear();
reset_auto_counter(module);
active_module = module;
active_sigmap.set(module);
+ active_modindex = ModIndex(module);
active_initdata.clear();
for (auto wire : module->wires())
@@ -1575,6 +1720,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
f << stringf("%s" "endmodule\n", indent.c_str());
active_module = NULL;
+ active_modindex = ModIndex();
active_sigmap.clear();
active_initdata.clear();
}
@@ -1605,7 +1751,12 @@ struct VerilogBackend : public Backend {
log("\n");
log(" -noexpr\n");
log(" without this option all internal cells are converted to Verilog\n");
- log(" expressions.\n");
+ log(" expressions. implies -noinline.\n");
+ log("\n");
+ log(" -noinline\n");
+ log(" without this option all internal cells driving a wire connected to\n");
+ log(" a single internal cell are inlined into that cell and the wire is\n");
+ log(" omitted.\n");
log("\n");
log(" -siminit\n");
log(" add initial statements with hierarchical refs to initialize FFs when\n");
@@ -1662,6 +1813,7 @@ struct VerilogBackend : public Backend {
noattr = false;
attr2comment = false;
noexpr = false;
+ noinline = false;
nodec = false;
nohex = false;
nostr = false;
@@ -1723,7 +1875,11 @@ struct VerilogBackend : public Backend {
continue;
}
if (arg == "-noexpr") {
- noexpr = true;
+ noexpr = noinline = true;
+ continue;
+ }
+ if (arg == "-noinline") {
+ noinline = true;
continue;
}
if (arg == "-nodec") {
diff --git a/kernel/modtools.h b/kernel/modtools.h
index 409562eb..b198709d 100644
--- a/kernel/modtools.h
+++ b/kernel/modtools.h
@@ -226,6 +226,10 @@ struct ModIndex : public RTLIL::Monitor
auto_reload_module = true;
}
+ ModIndex() : module(NULL)
+ {
+ }
+
ModIndex(RTLIL::Module *_m) : sigmap(_m), module(_m)
{
auto_reload_counter = 0;
@@ -235,7 +239,8 @@ struct ModIndex : public RTLIL::Monitor
~ModIndex()
{
- module->monitors.erase(this);
+ if (module)
+ module->monitors.erase(this);
}
SigBitInfo *query(RTLIL::SigBit bit)