mirror of https://github.com/YosysHQ/yosys.git
Merge remote-tracking branch 'origin/master' into xc7srl
This commit is contained in:
commit
f1a8e8a480
10
.travis.yml
10
.travis.yml
|
@ -132,11 +132,11 @@ matrix:
|
||||||
env:
|
env:
|
||||||
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
|
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
|
||||||
|
|
||||||
# Latest clang on Mac OS X
|
# # Latest clang on Mac OS X
|
||||||
- os: osx
|
# - os: osx
|
||||||
osx_image: xcode9.4
|
# osx_image: xcode9.4
|
||||||
env:
|
# env:
|
||||||
- MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
|
# - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- ./.travis/setup.sh
|
- ./.travis/setup.sh
|
||||||
|
|
5
Makefile
5
Makefile
|
@ -10,6 +10,7 @@ CONFIG := clang
|
||||||
# features (the more the better)
|
# features (the more the better)
|
||||||
ENABLE_TCL := 1
|
ENABLE_TCL := 1
|
||||||
ENABLE_ABC := 1
|
ENABLE_ABC := 1
|
||||||
|
ENABLE_GLOB := 1
|
||||||
ENABLE_PLUGINS := 1
|
ENABLE_PLUGINS := 1
|
||||||
ENABLE_READLINE := 1
|
ENABLE_READLINE := 1
|
||||||
ENABLE_EDITLINE := 0
|
ENABLE_EDITLINE := 0
|
||||||
|
@ -298,6 +299,10 @@ LDLIBS += -ldl
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ENABLE_GLOB),1)
|
||||||
|
CXXFLAGS += -DYOSYS_ENABLE_GLOB
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(ENABLE_TCL),1)
|
ifeq ($(ENABLE_TCL),1)
|
||||||
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
|
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
|
||||||
ifeq ($(OS), FreeBSD)
|
ifeq ($(OS), FreeBSD)
|
||||||
|
|
22
README.md
22
README.md
|
@ -34,11 +34,24 @@ compatible license that is similar in terms to the MIT license
|
||||||
or the 2-clause BSD license).
|
or the 2-clause BSD license).
|
||||||
|
|
||||||
|
|
||||||
Web Site
|
Web Site and Other Resources
|
||||||
========
|
============================
|
||||||
|
|
||||||
More information and documentation can be found on the Yosys web site:
|
More information and documentation can be found on the Yosys web site:
|
||||||
http://www.clifford.at/yosys/
|
- http://www.clifford.at/yosys/
|
||||||
|
|
||||||
|
The "Documentation" page on the web site contains links to more resources,
|
||||||
|
including a manual that even describes some of the Yosys internals:
|
||||||
|
- http://www.clifford.at/yosys/documentation.html
|
||||||
|
|
||||||
|
The file `CodingReadme` in this directory contains additional information
|
||||||
|
for people interested in using the Yosys C++ APIs.
|
||||||
|
|
||||||
|
Users interested in formal verification might want to use the formal verification
|
||||||
|
front-end for Yosys, SymbiYosys:
|
||||||
|
- https://symbiyosys.readthedocs.io/en/latest/
|
||||||
|
- https://github.com/YosysHQ/SymbiYosys
|
||||||
|
|
||||||
|
|
||||||
Setup
|
Setup
|
||||||
======
|
======
|
||||||
|
@ -296,6 +309,9 @@ Verilog Attributes and non-standard features
|
||||||
passes to identify input and output ports of cells. The Verilog backend
|
passes to identify input and output ports of cells. The Verilog backend
|
||||||
also does not output blackbox modules on default.
|
also does not output blackbox modules on default.
|
||||||
|
|
||||||
|
- The ``dynports'' attribute is used by the Verilog front-end to mark modules
|
||||||
|
that have ports with a width that depends on a parameter.
|
||||||
|
|
||||||
- The ``keep`` attribute on cells and wires is used to mark objects that should
|
- The ``keep`` attribute on cells and wires is used to mark objects that should
|
||||||
never be removed by the optimizer. This is used for example for cells that
|
never be removed by the optimizer. This is used for example for cells that
|
||||||
have hidden connections that are not part of the netlist, such as IO pads.
|
have hidden connections that are not part of the netlist, such as IO pads.
|
||||||
|
|
|
@ -130,7 +130,7 @@ struct EdifBackend : public Backend {
|
||||||
bool port_rename = false;
|
bool port_rename = false;
|
||||||
bool attr_properties = false;
|
bool attr_properties = false;
|
||||||
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
||||||
bool nogndvcc = false, gndvccy = true;
|
bool nogndvcc = false, gndvccy = false;
|
||||||
CellTypes ct(design);
|
CellTypes ct(design);
|
||||||
EdifNames edif_names;
|
EdifNames edif_names;
|
||||||
|
|
||||||
|
|
|
@ -165,11 +165,9 @@ struct FirrtlWorker
|
||||||
|
|
||||||
std::string fid(RTLIL::IdString internal_id)
|
std::string fid(RTLIL::IdString internal_id)
|
||||||
{
|
{
|
||||||
const char *str = internal_id.c_str();
|
return make_id(internal_id);
|
||||||
return *str == '\\' ? str + 1 : str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string cellname(RTLIL::Cell *cell)
|
std::string cellname(RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
return fid(cell->name).c_str();
|
return fid(cell->name).c_str();
|
||||||
|
@ -219,29 +217,42 @@ struct FirrtlWorker
|
||||||
if (it->second.size() > 0) {
|
if (it->second.size() > 0) {
|
||||||
const SigSpec &secondSig = it->second;
|
const SigSpec &secondSig = it->second;
|
||||||
const std::string firstName = cell_name + "." + make_id(it->first);
|
const std::string firstName = cell_name + "." + make_id(it->first);
|
||||||
const std::string secondName = make_expr(secondSig);
|
const std::string secondExpr = make_expr(secondSig);
|
||||||
// Find the direction for this port.
|
// Find the direction for this port.
|
||||||
FDirection dir = getPortFDirection(it->first, instModule);
|
FDirection dir = getPortFDirection(it->first, instModule);
|
||||||
std::string source, sink;
|
std::string sourceExpr, sinkExpr;
|
||||||
|
const SigSpec *sinkSig = nullptr;
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case FD_INOUT:
|
case FD_INOUT:
|
||||||
log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second));
|
log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second));
|
||||||
case FD_OUT:
|
case FD_OUT:
|
||||||
source = firstName;
|
sourceExpr = firstName;
|
||||||
sink = secondName;
|
sinkExpr = secondExpr;
|
||||||
|
sinkSig = &secondSig;
|
||||||
break;
|
break;
|
||||||
case FD_NODIRECTION:
|
case FD_NODIRECTION:
|
||||||
log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second));
|
log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second));
|
||||||
/* FALL_THROUGH */
|
/* FALL_THROUGH */
|
||||||
case FD_IN:
|
case FD_IN:
|
||||||
source = secondName;
|
sourceExpr = secondExpr;
|
||||||
sink = firstName;
|
sinkExpr = firstName;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir);
|
log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str()));
|
// Check for subfield assignment.
|
||||||
|
std::string bitsString = "bits(";
|
||||||
|
if (sinkExpr.substr(0, bitsString.length()) == bitsString ) {
|
||||||
|
if (sinkSig == nullptr)
|
||||||
|
log_error("Unknown subfield %s.%s\n", cell_type.c_str(), sinkExpr.c_str());
|
||||||
|
// Don't generate the assignment here.
|
||||||
|
// Add the source and sink to the "reverse_wire_map" and we'll output the assignment
|
||||||
|
// as part of the coalesced subfield assignments for this wire.
|
||||||
|
register_reverse_wire_map(sourceExpr, *sinkSig);
|
||||||
|
} else {
|
||||||
|
wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wire_exprs.push_back(stringf("\n"));
|
wire_exprs.push_back(stringf("\n"));
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct ProtobufDesignSerializer
|
||||||
|
|
||||||
ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
|
ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
|
||||||
aig_mode_(aig_mode), use_selection_(use_selection) { }
|
aig_mode_(aig_mode), use_selection_(use_selection) { }
|
||||||
|
|
||||||
string get_name(IdString name)
|
string get_name(IdString name)
|
||||||
{
|
{
|
||||||
return RTLIL::unescape_id(name);
|
return RTLIL::unescape_id(name);
|
||||||
|
@ -60,7 +60,7 @@ struct ProtobufDesignSerializer
|
||||||
{
|
{
|
||||||
for (auto ¶m : parameters) {
|
for (auto ¶m : parameters) {
|
||||||
std::string key = get_name(param.first);
|
std::string key = get_name(param.first);
|
||||||
|
|
||||||
|
|
||||||
yosys::pb::Parameter pb_param;
|
yosys::pb::Parameter pb_param;
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ struct ProtobufDesignSerializer
|
||||||
(*models)[aig.name] = pb_model;
|
(*models)[aig.name] = pb_model;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize_design(yosys::pb::Design *pb, Design *design)
|
void serialize_design(yosys::pb::Design *pb, Design *design)
|
||||||
{
|
{
|
||||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||||
|
|
|
@ -416,6 +416,7 @@ struct Smt2Worker
|
||||||
for (char ch : expr) {
|
for (char ch : expr) {
|
||||||
if (ch == 'A') processed_expr += get_bv(sig_a);
|
if (ch == 'A') processed_expr += get_bv(sig_a);
|
||||||
else if (ch == 'B') processed_expr += get_bv(sig_b);
|
else if (ch == 'B') processed_expr += get_bv(sig_b);
|
||||||
|
else if (ch == 'P') processed_expr += get_bv(cell->getPort("\\B"));
|
||||||
else if (ch == 'L') processed_expr += is_signed ? "a" : "l";
|
else if (ch == 'L') processed_expr += is_signed ? "a" : "l";
|
||||||
else if (ch == 'U') processed_expr += is_signed ? "s" : "u";
|
else if (ch == 'U') processed_expr += is_signed ? "s" : "u";
|
||||||
else processed_expr += ch;
|
else processed_expr += ch;
|
||||||
|
@ -554,7 +555,7 @@ struct Smt2Worker
|
||||||
|
|
||||||
if (cell->type.in("$shift", "$shiftx")) {
|
if (cell->type.in("$shift", "$shiftx")) {
|
||||||
if (cell->getParam("\\B_SIGNED").as_bool()) {
|
if (cell->getParam("\\B_SIGNED").as_bool()) {
|
||||||
return export_bvop(cell, stringf("(ite (bvsge B #b%0*d) "
|
return export_bvop(cell, stringf("(ite (bvsge P #b%0*d) "
|
||||||
"(bvlshr A B) (bvlshr A (bvneg B)))",
|
"(bvlshr A B) (bvlshr A (bvneg B)))",
|
||||||
GetSize(cell->getPort("\\B")), 0), 's');
|
GetSize(cell->getPort("\\B")), 0), 's');
|
||||||
} else {
|
} else {
|
||||||
|
@ -887,8 +888,8 @@ struct Smt2Worker
|
||||||
|
|
||||||
string name_a = get_bool(cell->getPort("\\A"));
|
string name_a = get_bool(cell->getPort("\\A"));
|
||||||
string name_en = get_bool(cell->getPort("\\EN"));
|
string name_en = get_bool(cell->getPort("\\EN"));
|
||||||
decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id,
|
string infostr = (cell->name[0] == '$' && cell->attributes.count("\\src")) ? cell->attributes.at("\\src").decode_string() : get_id(cell);
|
||||||
cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell)));
|
decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, infostr.c_str()));
|
||||||
|
|
||||||
if (cell->type == "$cover")
|
if (cell->type == "$cover")
|
||||||
decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n",
|
decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n",
|
||||||
|
@ -1103,20 +1104,27 @@ struct Smt2Worker
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Const initword = init_data.extract(i*width, width, State::Sx);
|
Const initword = init_data.extract(i*width, width, State::Sx);
|
||||||
|
Const initmask = initword;
|
||||||
bool gen_init_constr = false;
|
bool gen_init_constr = false;
|
||||||
|
|
||||||
for (auto bit : initword.bits)
|
for (int k = 0; k < GetSize(initword); k++) {
|
||||||
if (bit == State::S0 || bit == State::S1)
|
if (initword[k] == State::S0 || initword[k] == State::S1) {
|
||||||
gen_init_constr = true;
|
gen_init_constr = true;
|
||||||
|
initmask[k] = State::S1;
|
||||||
|
} else {
|
||||||
|
initmask[k] = State::S0;
|
||||||
|
initword[k] = State::S0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (gen_init_constr)
|
if (gen_init_constr)
|
||||||
{
|
{
|
||||||
if (statebv)
|
if (statebv)
|
||||||
/* FIXME */;
|
/* FIXME */;
|
||||||
else
|
else
|
||||||
init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]",
|
init_list.push_back(stringf("(= (bvand (select (|%s#%d#0| state) #b%s) #b%s) #b%s) ; %s[%d]",
|
||||||
get_id(module), arrayid, Const(i, abits).as_string().c_str(),
|
get_id(module), arrayid, Const(i, abits).as_string().c_str(),
|
||||||
initword.as_string().c_str(), get_id(cell), i));
|
initmask.as_string().c_str(), initword.as_string().c_str(), get_id(cell), i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal;
|
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal, siminit;
|
||||||
int auto_name_counter, auto_name_offset, auto_name_digits;
|
int auto_name_counter, auto_name_offset, auto_name_digits;
|
||||||
std::map<RTLIL::IdString, int> auto_name_map;
|
std::map<RTLIL::IdString, int> auto_name_map;
|
||||||
std::set<RTLIL::IdString> reg_wires, reg_ct;
|
std::set<RTLIL::IdString> reg_wires, reg_ct;
|
||||||
|
@ -1310,7 +1310,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg_ct.count(cell->type) && cell->hasPort("\\Q")) {
|
if (siminit && reg_ct.count(cell->type) && cell->hasPort("\\Q")) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
dump_reg_init(ss, cell->getPort("\\Q"));
|
dump_reg_init(ss, cell->getPort("\\Q"));
|
||||||
if (!ss.str().empty()) {
|
if (!ss.str().empty()) {
|
||||||
|
@ -1607,6 +1607,10 @@ struct VerilogBackend : public Backend {
|
||||||
log(" without this option all internal cells are converted to Verilog\n");
|
log(" without this option all internal cells are converted to Verilog\n");
|
||||||
log(" expressions.\n");
|
log(" expressions.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -siminit\n");
|
||||||
|
log(" add initial statements with hierarchical refs to initialize FFs when\n");
|
||||||
|
log(" in -noexpr mode.\n");
|
||||||
|
log("\n");
|
||||||
log(" -nodec\n");
|
log(" -nodec\n");
|
||||||
log(" 32-bit constant values are by default dumped as decimal numbers,\n");
|
log(" 32-bit constant values are by default dumped as decimal numbers,\n");
|
||||||
log(" not bit pattern. This option deactivates this feature and instead\n");
|
log(" not bit pattern. This option deactivates this feature and instead\n");
|
||||||
|
@ -1663,11 +1667,14 @@ struct VerilogBackend : public Backend {
|
||||||
nostr = false;
|
nostr = false;
|
||||||
defparam = false;
|
defparam = false;
|
||||||
decimal = false;
|
decimal = false;
|
||||||
|
siminit = false;
|
||||||
auto_prefix = "";
|
auto_prefix = "";
|
||||||
|
|
||||||
bool blackboxes = false;
|
bool blackboxes = false;
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
|
|
||||||
|
auto_name_map.clear();
|
||||||
|
reg_wires.clear();
|
||||||
reg_ct.clear();
|
reg_ct.clear();
|
||||||
|
|
||||||
reg_ct.insert("$dff");
|
reg_ct.insert("$dff");
|
||||||
|
@ -1739,6 +1746,10 @@ struct VerilogBackend : public Backend {
|
||||||
decimal = true;
|
decimal = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (arg == "-siminit") {
|
||||||
|
siminit = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (arg == "-blackboxes") {
|
if (arg == "-blackboxes") {
|
||||||
blackboxes = true;
|
blackboxes = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -1770,6 +1781,8 @@ struct VerilogBackend : public Backend {
|
||||||
dump_module(*f, "", it->second);
|
dump_module(*f, "", it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto_name_map.clear();
|
||||||
|
reg_wires.clear();
|
||||||
reg_ct.clear();
|
reg_ct.clear();
|
||||||
}
|
}
|
||||||
} VerilogBackend;
|
} VerilogBackend;
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
demo.bit
|
||||||
|
demo_phy.area
|
||||||
|
full.v
|
||||||
|
*.log
|
||||||
|
*.h
|
||||||
|
*.tde
|
||||||
|
*.svf
|
|
@ -0,0 +1,12 @@
|
||||||
|
LED Blink project for Anlogic Lichee Tang board.
|
||||||
|
|
||||||
|
Follow the install instructions for the Tang Dynasty IDE from given link below.
|
||||||
|
|
||||||
|
https://tang.sipeed.com/en/getting-started/installing-td-ide/linux/
|
||||||
|
|
||||||
|
|
||||||
|
set TD_HOME env variable to the full path to the TD <TD Install Directory> as follow.
|
||||||
|
|
||||||
|
export TD_HOME=<TD Install Directory>
|
||||||
|
|
||||||
|
then run "bash build.sh" in this directory.
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -ex
|
||||||
|
yosys demo.ys
|
||||||
|
$TD_HOME/bin/td build.tcl
|
|
@ -0,0 +1,11 @@
|
||||||
|
import_device eagle_s20.db -package BG256
|
||||||
|
read_verilog full.v -top demo
|
||||||
|
read_adc demo.adc
|
||||||
|
optimize_rtl
|
||||||
|
map_macro
|
||||||
|
map
|
||||||
|
pack
|
||||||
|
place
|
||||||
|
route
|
||||||
|
report_area -io_info -file demo_phy.area
|
||||||
|
bitgen -bit demo.bit -version 0X0000 -svf demo.svf -svf_comment_on -g ucode:00000000000000000000000000000000
|
|
@ -0,0 +1,2 @@
|
||||||
|
set_pin_assignment {CLK_IN} { LOCATION = K14; } ##24MHZ
|
||||||
|
set_pin_assignment {R_LED} { LOCATION = R3; } ##R_LED
|
|
@ -0,0 +1,18 @@
|
||||||
|
module demo (
|
||||||
|
input wire CLK_IN,
|
||||||
|
output wire R_LED
|
||||||
|
);
|
||||||
|
parameter time1 = 30'd12_000_000;
|
||||||
|
reg led_state;
|
||||||
|
reg [29:0] count;
|
||||||
|
|
||||||
|
always @(posedge CLK_IN)begin
|
||||||
|
if(count == time1)begin
|
||||||
|
count<= 30'd0;
|
||||||
|
led_state <= ~led_state;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
count <= count + 1'b1;
|
||||||
|
end
|
||||||
|
assign R_LED = led_state;
|
||||||
|
endmodule
|
|
@ -0,0 +1,3 @@
|
||||||
|
read_verilog demo.v
|
||||||
|
synth_anlogic -top demo
|
||||||
|
write_verilog full.v
|
|
@ -1,3 +1,4 @@
|
||||||
/netlist.edn
|
/netlist.edn
|
||||||
/netlist.vm
|
/netlist.vm
|
||||||
|
/example.stp
|
||||||
/proj
|
/proj
|
||||||
|
|
|
@ -1 +1,20 @@
|
||||||
# Add placement constraints here
|
# Add placement constraints here
|
||||||
|
|
||||||
|
set_io clk -pinname H16 -fixed yes -DIRECTION INPUT
|
||||||
|
|
||||||
|
set_io SW1 -pinname H12 -fixed yes -DIRECTION INPUT
|
||||||
|
set_io SW2 -pinname H13 -fixed yes -DIRECTION INPUT
|
||||||
|
|
||||||
|
set_io LED1 -pinname J16 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io LED2 -pinname M16 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io LED3 -pinname K16 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io LED4 -pinname N16 -fixed yes -DIRECTION OUTPUT
|
||||||
|
|
||||||
|
set_io AA -pinname L12 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io AB -pinname L13 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io AC -pinname M13 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io AD -pinname N15 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io AE -pinname L11 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io AF -pinname L14 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io AG -pinname N14 -fixed yes -DIRECTION OUTPUT
|
||||||
|
set_io CA -pinname M15 -fixed yes -DIRECTION OUTPUT
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
# Add timing constraints here
|
# Add timing constraints here
|
||||||
|
create_clock -period 10.000 -waveform {0.000 5.000} [get_ports {clk}]
|
||||||
|
|
|
@ -1,23 +1,64 @@
|
||||||
module example (
|
module example (
|
||||||
input clk,
|
input clk,
|
||||||
input EN,
|
input SW1,
|
||||||
|
input SW2,
|
||||||
output LED1,
|
output LED1,
|
||||||
output LED2,
|
output LED2,
|
||||||
output LED3,
|
output LED3,
|
||||||
output LED4,
|
output LED4,
|
||||||
output LED5
|
|
||||||
|
output AA, AB, AC, AD,
|
||||||
|
output AE, AF, AG, CA
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam BITS = 5;
|
localparam BITS = 8;
|
||||||
localparam LOG2DELAY = 22;
|
localparam LOG2DELAY = 22;
|
||||||
|
|
||||||
reg [BITS+LOG2DELAY-1:0] counter = 0;
|
reg [BITS+LOG2DELAY-1:0] counter = 0;
|
||||||
reg [BITS-1:0] outcnt;
|
reg [BITS-1:0] outcnt;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
counter <= counter + EN;
|
counter <= counter + SW1 + SW2 + 1;
|
||||||
outcnt <= counter >> LOG2DELAY;
|
outcnt <= counter >> LOG2DELAY;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign {LED1, LED2, LED3, LED4, LED5} = outcnt ^ (outcnt >> 1);
|
assign {LED1, LED2, LED3, LED4} = outcnt ^ (outcnt >> 1);
|
||||||
|
|
||||||
|
// assign CA = counter[10];
|
||||||
|
// seg7enc seg7encinst (
|
||||||
|
// .seg({AA, AB, AC, AD, AE, AF, AG}),
|
||||||
|
// .dat(CA ? outcnt[3:0] : outcnt[7:4])
|
||||||
|
// );
|
||||||
|
|
||||||
|
assign {AA, AB, AC, AD, AE, AF, AG} = ~(7'b 100_0000 >> outcnt[6:4]);
|
||||||
|
assign CA = outcnt[7];
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module seg7enc (
|
||||||
|
input [3:0] dat,
|
||||||
|
output [6:0] seg
|
||||||
|
);
|
||||||
|
reg [6:0] seg_inv;
|
||||||
|
always @* begin
|
||||||
|
seg_inv = 0;
|
||||||
|
case (dat)
|
||||||
|
4'h0: seg_inv = 7'b 0111111;
|
||||||
|
4'h1: seg_inv = 7'b 0000110;
|
||||||
|
4'h2: seg_inv = 7'b 1011011;
|
||||||
|
4'h3: seg_inv = 7'b 1001111;
|
||||||
|
4'h4: seg_inv = 7'b 1100110;
|
||||||
|
4'h5: seg_inv = 7'b 1101101;
|
||||||
|
4'h6: seg_inv = 7'b 1111101;
|
||||||
|
4'h7: seg_inv = 7'b 0000111;
|
||||||
|
4'h8: seg_inv = 7'b 1111111;
|
||||||
|
4'h9: seg_inv = 7'b 1101111;
|
||||||
|
4'hA: seg_inv = 7'b 1110111;
|
||||||
|
4'hB: seg_inv = 7'b 1111100;
|
||||||
|
4'hC: seg_inv = 7'b 0111001;
|
||||||
|
4'hD: seg_inv = 7'b 1011110;
|
||||||
|
4'hE: seg_inv = 7'b 1111001;
|
||||||
|
4'hF: seg_inv = 7'b 1110001;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
assign seg = ~seg_inv;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -8,13 +8,14 @@ new_project \
|
||||||
-block_mode 0 \
|
-block_mode 0 \
|
||||||
-hdl "VERILOG" \
|
-hdl "VERILOG" \
|
||||||
-family IGLOO2 \
|
-family IGLOO2 \
|
||||||
-die PA4MGL500 \
|
-die PA4MGL2500 \
|
||||||
-package tq144 \
|
-package vf256 \
|
||||||
-speed -1
|
-speed -1
|
||||||
|
|
||||||
import_files -hdl_source {netlist.vm}
|
import_files -hdl_source {netlist.vm}
|
||||||
import_files -sdc {example.sdc}
|
import_files -sdc {example.sdc}
|
||||||
import_files -io_pdc {example.pdc}
|
import_files -io_pdc {example.pdc}
|
||||||
|
build_design_hierarchy
|
||||||
set_option -synth 0
|
set_option -synth 0
|
||||||
|
|
||||||
organize_tool_files -tool PLACEROUTE \
|
organize_tool_files -tool PLACEROUTE \
|
||||||
|
@ -32,22 +33,25 @@ configure_tool -name PLACEROUTE \
|
||||||
-params EFFORT_LEVEL:false \
|
-params EFFORT_LEVEL:false \
|
||||||
-params REPAIR_MIN_DELAY:false
|
-params REPAIR_MIN_DELAY:false
|
||||||
|
|
||||||
|
puts ""
|
||||||
puts "**> COMPILE"
|
puts "**> COMPILE"
|
||||||
run_tool -name {COMPILE}
|
run_tool -name {COMPILE}
|
||||||
puts "<** COMPILE"
|
puts "<** COMPILE"
|
||||||
|
|
||||||
|
puts ""
|
||||||
puts "**> PLACEROUTE"
|
puts "**> PLACEROUTE"
|
||||||
run_tool -name {PLACEROUTE}
|
run_tool -name {PLACEROUTE}
|
||||||
puts "<** PLACEROUTE"
|
puts "<** PLACEROUTE"
|
||||||
|
|
||||||
|
puts ""
|
||||||
puts "**> VERIFYTIMING"
|
puts "**> VERIFYTIMING"
|
||||||
run_tool -name {VERIFYTIMING}
|
run_tool -name {VERIFYTIMING}
|
||||||
puts "<** VERIFYTIMING"
|
puts "<** VERIFYTIMING"
|
||||||
|
|
||||||
save_project
|
puts ""
|
||||||
|
puts "**> BITSTREAM"
|
||||||
# puts "**> export_bitstream"
|
export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
|
||||||
# export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
|
puts "<** BITSTREAM"
|
||||||
# puts "<** export_bitstream"
|
|
||||||
|
|
||||||
|
puts ""
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -ex
|
set -ex
|
||||||
yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v
|
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
|
export LM_LICENSE_FILE=${LM_LICENSE_FILE:-1702@localhost}
|
||||||
|
/opt/microsemi/Libero_SoC_v12.0/Libero/bin/libero SCRIPT:libero.tcl
|
||||||
|
cp proj/designer/example/export/example.stp .
|
||||||
|
|
|
@ -214,6 +214,8 @@ namespace AST
|
||||||
MEM2REG_FL_SET_ASYNC = 0x00000800,
|
MEM2REG_FL_SET_ASYNC = 0x00000800,
|
||||||
MEM2REG_FL_EQ2 = 0x00001000,
|
MEM2REG_FL_EQ2 = 0x00001000,
|
||||||
MEM2REG_FL_CMPLX_LHS = 0x00002000,
|
MEM2REG_FL_CMPLX_LHS = 0x00002000,
|
||||||
|
MEM2REG_FL_CONST_LHS = 0x00004000,
|
||||||
|
MEM2REG_FL_VAR_LHS = 0x00008000,
|
||||||
|
|
||||||
/* proc flags */
|
/* proc flags */
|
||||||
MEM2REG_FL_EQ1 = 0x01000000,
|
MEM2REG_FL_EQ1 = 0x01000000,
|
||||||
|
@ -237,6 +239,7 @@ namespace AST
|
||||||
bool has_const_only_constructs(bool &recommend_const_eval);
|
bool has_const_only_constructs(bool &recommend_const_eval);
|
||||||
void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
|
void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
|
||||||
AstNode *eval_const_function(AstNode *fcall);
|
AstNode *eval_const_function(AstNode *fcall);
|
||||||
|
bool is_simple_const_expr();
|
||||||
|
|
||||||
// create a human-readable text representation of the AST (for debugging)
|
// create a human-readable text representation of the AST (for debugging)
|
||||||
void dumpAst(FILE *f, std::string indent) const;
|
void dumpAst(FILE *f, std::string indent) const;
|
||||||
|
|
|
@ -544,7 +544,11 @@ struct AST_INTERNAL::ProcessGenerator
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AST_WIRE:
|
case AST_WIRE:
|
||||||
log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n");
|
log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AST_ASSIGN:
|
||||||
|
log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AST_PARAMETER:
|
case AST_PARAMETER:
|
||||||
|
@ -1409,10 +1413,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
||||||
if (GetSize(en) != 1)
|
if (GetSize(en) != 1)
|
||||||
en = current_module->ReduceBool(NEW_ID, en);
|
en = current_module->ReduceBool(NEW_ID, en);
|
||||||
|
|
||||||
std::stringstream sstr;
|
IdString cellname;
|
||||||
sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++);
|
if (str.empty()) {
|
||||||
|
std::stringstream sstr;
|
||||||
|
sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++);
|
||||||
|
cellname = sstr.str();
|
||||||
|
} else {
|
||||||
|
cellname = str;
|
||||||
|
}
|
||||||
|
|
||||||
RTLIL::Cell *cell = current_module->addCell(sstr.str(), celltype);
|
RTLIL::Cell *cell = current_module->addCell(cellname, celltype);
|
||||||
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
|
||||||
|
|
||||||
for (auto &attr : attributes) {
|
for (auto &attr : attributes) {
|
||||||
|
|
|
@ -50,7 +50,6 @@ using namespace AST_INTERNAL;
|
||||||
bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
|
bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param)
|
||||||
{
|
{
|
||||||
static int recursion_counter = 0;
|
static int recursion_counter = 0;
|
||||||
static pair<string, int> last_blocking_assignment_warn;
|
|
||||||
static bool deep_recursion_warning = false;
|
static bool deep_recursion_warning = false;
|
||||||
|
|
||||||
if (recursion_counter++ == 1000 && deep_recursion_warning) {
|
if (recursion_counter++ == 1000 && deep_recursion_warning) {
|
||||||
|
@ -72,7 +71,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
if (stage == 0)
|
if (stage == 0)
|
||||||
{
|
{
|
||||||
log_assert(type == AST_MODULE || type == AST_INTERFACE);
|
log_assert(type == AST_MODULE || type == AST_INTERFACE);
|
||||||
last_blocking_assignment_warn = pair<string, int>();
|
|
||||||
|
|
||||||
deep_recursion_warning = true;
|
deep_recursion_warning = true;
|
||||||
while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { }
|
while (simplify(const_fold, at_zero, in_lvalue, 1, width_hint, sign_hint, in_param)) { }
|
||||||
|
@ -113,6 +111,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)
|
if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)
|
||||||
goto verbose_activate;
|
goto verbose_activate;
|
||||||
|
|
||||||
|
if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS))
|
||||||
|
goto verbose_activate;
|
||||||
|
|
||||||
// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
|
// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -325,6 +326,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
for (size_t i = 0; i < children.size(); i++) {
|
for (size_t i = 0; i < children.size(); i++) {
|
||||||
AstNode *node = children[i];
|
AstNode *node = children[i];
|
||||||
if (node->type == AST_WIRE) {
|
if (node->type == AST_WIRE) {
|
||||||
|
if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
|
||||||
|
for (auto c : node->children[0]->children) {
|
||||||
|
if (!c->is_simple_const_expr()) {
|
||||||
|
if (attributes.count("\\dynports"))
|
||||||
|
delete attributes.at("\\dynports");
|
||||||
|
attributes["\\dynports"] = AstNode::mkconst_int(1, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this_wire_scope.count(node->str) > 0) {
|
if (this_wire_scope.count(node->str) > 0) {
|
||||||
AstNode *first_node = this_wire_scope[node->str];
|
AstNode *first_node = this_wire_scope[node->str];
|
||||||
if (first_node->is_input && node->is_reg)
|
if (first_node->is_input && node->is_reg)
|
||||||
|
@ -938,7 +948,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (current_scope.count(str) == 0) {
|
if (current_scope.count(str) == 0) {
|
||||||
if (flag_autowire) {
|
if (flag_autowire || str == "\\$global_clock") {
|
||||||
AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
|
AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
|
||||||
auto_wire->str = str;
|
auto_wire->str = str;
|
||||||
current_ast_mod->children.push_back(auto_wire);
|
current_ast_mod->children.push_back(auto_wire);
|
||||||
|
@ -1499,6 +1509,7 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
newNode->children.push_back(assign_en);
|
newNode->children.push_back(assign_en);
|
||||||
|
|
||||||
AstNode *assertnode = new AstNode(type);
|
AstNode *assertnode = new AstNode(type);
|
||||||
|
assertnode->str = str;
|
||||||
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
|
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
|
||||||
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
|
assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
|
||||||
assertnode->children[0]->str = id_check;
|
assertnode->children[0]->str = id_check;
|
||||||
|
@ -1579,14 +1590,6 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
|
sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);
|
||||||
std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
|
std::string id_addr = sstr.str() + "_ADDR", id_data = sstr.str() + "_DATA", id_en = sstr.str() + "_EN";
|
||||||
|
|
||||||
if (type == AST_ASSIGN_EQ) {
|
|
||||||
pair<string, int> this_blocking_assignment_warn(filename, linenum);
|
|
||||||
if (this_blocking_assignment_warn != last_blocking_assignment_warn)
|
|
||||||
log_warning("Blocking assignment to memory in line %s:%d is handled like a non-blocking assignment.\n",
|
|
||||||
filename.c_str(), linenum);
|
|
||||||
last_blocking_assignment_warn = this_blocking_assignment_warn;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mem_width, mem_size, addr_bits;
|
int mem_width, mem_size, addr_bits;
|
||||||
bool mem_signed = children[0]->id2ast->is_signed;
|
bool mem_signed = children[0]->id2ast->is_signed;
|
||||||
children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
|
children[0]->id2ast->meminfo(mem_width, mem_size, addr_bits);
|
||||||
|
@ -2169,6 +2172,8 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
}
|
}
|
||||||
|
|
||||||
newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init);
|
newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init);
|
||||||
|
delete node_filename;
|
||||||
|
delete node_memory;
|
||||||
goto apply_newNode;
|
goto apply_newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2210,6 +2215,8 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
std::map<std::string, std::string> replace_rules;
|
std::map<std::string, std::string> replace_rules;
|
||||||
vector<AstNode*> added_mod_children;
|
vector<AstNode*> added_mod_children;
|
||||||
dict<std::string, AstNode*> wire_cache;
|
dict<std::string, AstNode*> wire_cache;
|
||||||
|
vector<AstNode*> new_stmts;
|
||||||
|
vector<AstNode*> output_assignments;
|
||||||
|
|
||||||
if (current_block == NULL)
|
if (current_block == NULL)
|
||||||
{
|
{
|
||||||
|
@ -2334,8 +2341,8 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
wire->port_id = 0;
|
wire->port_id = 0;
|
||||||
wire->is_input = false;
|
wire->is_input = false;
|
||||||
wire->is_output = false;
|
wire->is_output = false;
|
||||||
if (!child->is_output)
|
wire->is_reg = true;
|
||||||
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
wire_cache[child->str] = wire;
|
wire_cache[child->str] = wire;
|
||||||
|
|
||||||
current_ast_mod->children.push_back(wire);
|
current_ast_mod->children.push_back(wire);
|
||||||
|
@ -2357,13 +2364,10 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
|
new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
|
||||||
new AstNode(AST_ASSIGN_EQ, arg, wire_id);
|
new AstNode(AST_ASSIGN_EQ, arg, wire_id);
|
||||||
assign->children[0]->was_checked = true;
|
assign->children[0]->was_checked = true;
|
||||||
|
if (child->is_input)
|
||||||
for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
|
new_stmts.push_back(assign);
|
||||||
if (*it != current_block_child)
|
else
|
||||||
continue;
|
output_assignments.push_back(assign);
|
||||||
current_block->children.insert(it, assign);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2377,15 +2381,19 @@ skip_dynamic_range_lvalue_expansion:;
|
||||||
{
|
{
|
||||||
AstNode *stmt = child->clone();
|
AstNode *stmt = child->clone();
|
||||||
stmt->replace_ids(prefix, replace_rules);
|
stmt->replace_ids(prefix, replace_rules);
|
||||||
|
new_stmts.push_back(stmt);
|
||||||
for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
|
|
||||||
if (*it != current_block_child)
|
|
||||||
continue;
|
|
||||||
current_block->children.insert(it, stmt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_stmts.insert(new_stmts.end(), output_assignments.begin(), output_assignments.end());
|
||||||
|
|
||||||
|
for (auto it = current_block->children.begin(); ; it++) {
|
||||||
|
log_assert(it != current_block->children.end());
|
||||||
|
if (*it == current_block_child) {
|
||||||
|
current_block->children.insert(it, new_stmts.begin(), new_stmts.end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
replace_fcall_with_id:
|
replace_fcall_with_id:
|
||||||
if (type == AST_FCALL) {
|
if (type == AST_FCALL) {
|
||||||
delete_children();
|
delete_children();
|
||||||
|
@ -2910,7 +2918,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
|
||||||
dict<AstNode*, uint32_t> &mem2reg_candidates, dict<AstNode*, uint32_t> &proc_flags, uint32_t &flags)
|
dict<AstNode*, uint32_t> &mem2reg_candidates, dict<AstNode*, uint32_t> &proc_flags, uint32_t &flags)
|
||||||
{
|
{
|
||||||
uint32_t children_flags = 0;
|
uint32_t children_flags = 0;
|
||||||
int ignore_children_counter = 0;
|
int lhs_children_counter = 0;
|
||||||
|
|
||||||
if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
|
if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
|
||||||
{
|
{
|
||||||
|
@ -2936,6 +2944,16 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
|
||||||
proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
|
proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for proper (non-init) writes: remember if this is a constant index or not
|
||||||
|
if ((flags & MEM2REG_FL_INIT) == 0) {
|
||||||
|
if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) {
|
||||||
|
if (children[0]->children[0]->children[0]->type == AST_CONSTANT)
|
||||||
|
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS;
|
||||||
|
else
|
||||||
|
mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// remember where this is
|
// remember where this is
|
||||||
if (flags & MEM2REG_FL_INIT) {
|
if (flags & MEM2REG_FL_INIT) {
|
||||||
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
|
if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT))
|
||||||
|
@ -2948,7 +2966,7 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ignore_children_counter = 1;
|
lhs_children_counter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY)
|
if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY)
|
||||||
|
@ -2991,12 +3009,23 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
|
||||||
log_assert((flags & ~0x000000ff) == 0);
|
log_assert((flags & ~0x000000ff) == 0);
|
||||||
|
|
||||||
for (auto child : children)
|
for (auto child : children)
|
||||||
if (ignore_children_counter > 0)
|
{
|
||||||
ignore_children_counter--;
|
if (lhs_children_counter > 0) {
|
||||||
else if (proc_flags_p)
|
lhs_children_counter--;
|
||||||
|
if (child->children.size() && child->children[0]->type == AST_RANGE && child->children[0]->children.size()) {
|
||||||
|
for (auto c : child->children[0]->children) {
|
||||||
|
if (proc_flags_p)
|
||||||
|
c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
|
||||||
|
else
|
||||||
|
c->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (proc_flags_p)
|
||||||
child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
|
child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, *proc_flags_p, flags);
|
||||||
else
|
else
|
||||||
child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
|
child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, flags);
|
||||||
|
}
|
||||||
|
|
||||||
flags &= ~children_flags | backup_flags;
|
flags &= ~children_flags | backup_flags;
|
||||||
|
|
||||||
|
@ -3048,6 +3077,39 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
||||||
if (type == AST_FUNCTION || type == AST_TASK)
|
if (type == AST_FUNCTION || type == AST_TASK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))
|
||||||
|
{
|
||||||
|
log_assert(children[0]->type == AST_CONSTANT);
|
||||||
|
log_assert(children[1]->type == AST_CONSTANT);
|
||||||
|
log_assert(children[2]->type == AST_CONSTANT);
|
||||||
|
|
||||||
|
int cursor = children[0]->asInt(false);
|
||||||
|
Const data = children[1]->bitsAsConst();
|
||||||
|
int length = children[2]->asInt(false);
|
||||||
|
|
||||||
|
if (length != 0)
|
||||||
|
{
|
||||||
|
AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK));
|
||||||
|
mod->children.push_back(block);
|
||||||
|
block = block->children[0];
|
||||||
|
|
||||||
|
int wordsz = GetSize(data) / length;
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false)));
|
||||||
|
block->children.back()->children[0]->str = str;
|
||||||
|
block->children.back()->children[0]->id2ast = id2ast;
|
||||||
|
block->children.back()->children[0]->was_checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *newNode = new AstNode(AST_NONE);
|
||||||
|
newNode->cloneInto(this);
|
||||||
|
delete newNode;
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))
|
if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))
|
||||||
{
|
{
|
||||||
if (async_block == NULL) {
|
if (async_block == NULL) {
|
||||||
|
@ -3277,6 +3339,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AstNode::is_simple_const_expr()
|
||||||
|
{
|
||||||
|
if (type == AST_IDENTIFIER)
|
||||||
|
return false;
|
||||||
|
for (auto child : children)
|
||||||
|
if (!child->is_simple_const_expr())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// helper function for AstNode::eval_const_function()
|
// helper function for AstNode::eval_const_function()
|
||||||
void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
|
void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,7 @@ Then run in the following command in this directory:
|
||||||
|
|
||||||
sby -f example.sby
|
sby -f example.sby
|
||||||
|
|
||||||
This will generate approximately one page of text outpout. The last lines
|
This will generate approximately one page of text output. The last lines
|
||||||
should be something like this:
|
should be something like this:
|
||||||
|
|
||||||
SBY [example] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0)
|
SBY [example] summary: Elapsed clock time [H:MM:SS (secs)]: 0:00:00 (0)
|
||||||
|
|
|
@ -1855,6 +1855,13 @@ struct VerificPass : public Pass {
|
||||||
log(" -autocover\n");
|
log(" -autocover\n");
|
||||||
log(" Generate automatic cover statements for all asserts\n");
|
log(" Generate automatic cover statements for all asserts\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -chparam name value \n");
|
||||||
|
log(" Elaborate the specified top modules (all modules when -all given) using\n");
|
||||||
|
log(" this parameter value. Modules on which this parameter does not exist will\n");
|
||||||
|
log(" cause Verific to produce a VERI-1928 or VHDL-1676 message. This option\n");
|
||||||
|
log(" can be specified multiple times to override multiple parameters.\n");
|
||||||
|
log(" String values must be passed in double quotes (\").\n");
|
||||||
|
log("\n");
|
||||||
log(" -v, -vv\n");
|
log(" -v, -vv\n");
|
||||||
log(" Verbose log messages. (-vv is even more verbose than -v.)\n");
|
log(" Verbose log messages. (-vv is even more verbose than -v.)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -2109,6 +2116,7 @@ struct VerificPass : public Pass {
|
||||||
bool mode_autocover = false;
|
bool mode_autocover = false;
|
||||||
bool flatten = false, extnets = false;
|
bool flatten = false, extnets = false;
|
||||||
string dumpfile;
|
string dumpfile;
|
||||||
|
Map parameters(STRING_HASH);
|
||||||
|
|
||||||
for (argidx++; argidx < GetSize(args); argidx++) {
|
for (argidx++; argidx < GetSize(args); argidx++) {
|
||||||
if (args[argidx] == "-all") {
|
if (args[argidx] == "-all") {
|
||||||
|
@ -2147,6 +2155,15 @@ struct VerificPass : public Pass {
|
||||||
mode_autocover = true;
|
mode_autocover = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) {
|
||||||
|
const std::string &key = args[++argidx];
|
||||||
|
const std::string &value = args[++argidx];
|
||||||
|
unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(),
|
||||||
|
1 /* force_overwrite */);
|
||||||
|
if (!new_insertion)
|
||||||
|
log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-V") {
|
if (args[argidx] == "-V") {
|
||||||
mode_verific = true;
|
mode_verific = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -2180,7 +2197,7 @@ struct VerificPass : public Pass {
|
||||||
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
|
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
|
||||||
if (veri_lib) veri_libs.InsertLast(veri_lib);
|
if (veri_lib) veri_libs.InsertLast(veri_lib);
|
||||||
|
|
||||||
Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs);
|
Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, ¶meters);
|
||||||
Netlist *nl;
|
Netlist *nl;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -2217,7 +2234,7 @@ struct VerificPass : public Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
log("Running hier_tree::Elaborate().\n");
|
log("Running hier_tree::Elaborate().\n");
|
||||||
Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units);
|
Array *netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units, ¶meters);
|
||||||
Netlist *nl;
|
Netlist *nl;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -2316,7 +2333,7 @@ struct ReadPass : public Pass {
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
{
|
{
|
||||||
if (args.size() < 2)
|
if (args.size() < 2 || args[1][0] != '-')
|
||||||
log_cmd_error("Missing mode parameter.\n");
|
log_cmd_error("Missing mode parameter.\n");
|
||||||
|
|
||||||
if (args.size() < 3)
|
if (args.size() < 3)
|
||||||
|
|
|
@ -1666,7 +1666,20 @@ struct VerificSvaImporter
|
||||||
log(" importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(),
|
log(" importing SVA property at root cell %s (%s) at %s:%d.\n", root->Name(), root->View()->Owner()->Name(),
|
||||||
LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile()));
|
LineFile::GetFileName(root->Linefile()), LineFile::GetLineNo(root->Linefile()));
|
||||||
|
|
||||||
RTLIL::IdString root_name = module->uniquify(importer->mode_names || root->IsUserDeclared() ? RTLIL::escape_id(root->Name()) : NEW_ID);
|
bool is_user_declared = root->IsUserDeclared();
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
if (!is_user_declared) {
|
||||||
|
const char *name = root->Name();
|
||||||
|
for (int i = 0; name[i]; i++) {
|
||||||
|
if (i ? (name[i] < '0' || name[i] > '9') : (name[i] != 'i')) {
|
||||||
|
is_user_declared = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RTLIL::IdString root_name = module->uniquify(importer->mode_names || is_user_declared ? RTLIL::escape_id(root->Name()) : NEW_ID);
|
||||||
|
|
||||||
// parse SVA sequence into trigger signal
|
// parse SVA sequence into trigger signal
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,14 @@ YOSYS_NAMESPACE_END
|
||||||
"always_ff" { SV_KEYWORD(TOK_ALWAYS); }
|
"always_ff" { SV_KEYWORD(TOK_ALWAYS); }
|
||||||
"always_latch" { SV_KEYWORD(TOK_ALWAYS); }
|
"always_latch" { SV_KEYWORD(TOK_ALWAYS); }
|
||||||
|
|
||||||
|
/* use special token for labels on assert, assume, cover, and restrict because it's insanley complex
|
||||||
|
to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
|
||||||
|
global state.. its a mess) */
|
||||||
|
[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
|
||||||
|
frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
|
||||||
|
return TOK_SVA_LABEL;
|
||||||
|
}
|
||||||
|
|
||||||
"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
|
"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
|
||||||
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
|
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
|
||||||
"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
|
"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
|
||||||
|
@ -303,7 +311,7 @@ supply1 { return TOK_SUPPLY1; }
|
||||||
|
|
||||||
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
|
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
|
||||||
frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
|
frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
|
||||||
return TOK_ID;
|
return TOK_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
|
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
|
||||||
|
|
|
@ -105,7 +105,8 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
||||||
bool boolean;
|
bool boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
|
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE TOK_SVA_LABEL
|
||||||
|
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER
|
||||||
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
|
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
|
||||||
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
||||||
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
|
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
|
||||||
|
@ -119,14 +120,13 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
||||||
%token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
|
%token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
|
||||||
%token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
|
%token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
|
||||||
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
|
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
|
||||||
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME
|
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
|
||||||
%token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
|
|
||||||
%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
|
%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
|
||||||
%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY
|
%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY
|
||||||
|
|
||||||
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
|
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
|
||||||
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
|
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
|
||||||
%type <string> opt_label tok_prim_wrapper hierarchical_id
|
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id
|
||||||
%type <boolean> opt_signed opt_property unique_case_attr
|
%type <boolean> opt_signed opt_property unique_case_attr
|
||||||
%type <al> attr case_attr
|
%type <al> attr case_attr
|
||||||
|
|
||||||
|
@ -1329,6 +1329,14 @@ opt_label:
|
||||||
$$ = NULL;
|
$$ = NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
opt_sva_label:
|
||||||
|
TOK_SVA_LABEL ':' {
|
||||||
|
$$ = $1;
|
||||||
|
} |
|
||||||
|
/* empty */ {
|
||||||
|
$$ = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
opt_property:
|
opt_property:
|
||||||
TOK_PROPERTY {
|
TOK_PROPERTY {
|
||||||
$$ = true;
|
$$ = true;
|
||||||
|
@ -1337,9 +1345,6 @@ opt_property:
|
||||||
$$ = false;
|
$$ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
opt_stmt_label:
|
|
||||||
TOK_ID ':' | /* empty */;
|
|
||||||
|
|
||||||
modport_stmt:
|
modport_stmt:
|
||||||
TOK_MODPORT TOK_ID {
|
TOK_MODPORT TOK_ID {
|
||||||
AstNode *modport = new AstNode(AST_MODPORT);
|
AstNode *modport = new AstNode(AST_MODPORT);
|
||||||
|
@ -1376,83 +1381,164 @@ modport_type_token:
|
||||||
TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;}
|
TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;}
|
||||||
|
|
||||||
assert:
|
assert:
|
||||||
opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {
|
opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' {
|
||||||
if (noassert_mode)
|
if (noassert_mode) {
|
||||||
delete $5;
|
delete $5;
|
||||||
else
|
} else {
|
||||||
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
|
AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5);
|
||||||
|
if ($1 != nullptr)
|
||||||
|
node->str = *$1;
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
|
}
|
||||||
|
if ($1 != nullptr)
|
||||||
|
delete $1;
|
||||||
} |
|
} |
|
||||||
opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' {
|
opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' {
|
||||||
if (noassume_mode)
|
if (noassume_mode) {
|
||||||
delete $5;
|
delete $5;
|
||||||
else
|
} else {
|
||||||
ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5));
|
AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5);
|
||||||
|
if ($1 != nullptr)
|
||||||
|
node->str = *$1;
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
|
}
|
||||||
|
if ($1 != nullptr)
|
||||||
|
delete $1;
|
||||||
} |
|
} |
|
||||||
opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
||||||
if (noassert_mode)
|
if (noassert_mode) {
|
||||||
delete $6;
|
delete $6;
|
||||||
else
|
} else {
|
||||||
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
|
AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6);
|
||||||
|
if ($1 != nullptr)
|
||||||
|
node->str = *$1;
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
|
}
|
||||||
|
if ($1 != nullptr)
|
||||||
|
delete $1;
|
||||||
} |
|
} |
|
||||||
opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
||||||
if (noassume_mode)
|
if (noassume_mode) {
|
||||||
delete $6;
|
delete $6;
|
||||||
else
|
} else {
|
||||||
ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6));
|
AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6);
|
||||||
|
if ($1 != nullptr)
|
||||||
|
node->str = *$1;
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
|
}
|
||||||
|
if ($1 != nullptr)
|
||||||
|
delete $1;
|
||||||
} |
|
} |
|
||||||
opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' {
|
opt_sva_label TOK_COVER opt_property '(' expr ')' ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
|
AstNode *node = new AstNode(AST_COVER, $5);
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
node->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
} |
|
} |
|
||||||
opt_stmt_label TOK_COVER opt_property '(' ')' ';' {
|
opt_sva_label TOK_COVER opt_property '(' ')' ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
|
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
node->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
} |
|
} |
|
||||||
opt_stmt_label TOK_COVER ';' {
|
opt_sva_label TOK_COVER ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
|
AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
node->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
} |
|
} |
|
||||||
opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' {
|
opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' {
|
||||||
if (norestrict_mode)
|
if (norestrict_mode) {
|
||||||
delete $5;
|
delete $5;
|
||||||
else
|
} else {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
|
AstNode *node = new AstNode(AST_ASSUME, $5);
|
||||||
|
if ($1 != nullptr)
|
||||||
|
node->str = *$1;
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
|
}
|
||||||
if (!$3)
|
if (!$3)
|
||||||
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
|
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
|
||||||
|
if ($1 != nullptr)
|
||||||
|
delete $1;
|
||||||
} |
|
} |
|
||||||
opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
||||||
if (norestrict_mode)
|
if (norestrict_mode) {
|
||||||
delete $6;
|
delete $6;
|
||||||
else
|
} else {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
|
AstNode *node = new AstNode(AST_FAIR, $6);
|
||||||
|
if ($1 != nullptr)
|
||||||
|
node->str = *$1;
|
||||||
|
ast_stack.back()->children.push_back(node);
|
||||||
|
}
|
||||||
if (!$3)
|
if (!$3)
|
||||||
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
|
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
|
||||||
|
if ($1 != nullptr)
|
||||||
|
delete $1;
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_property:
|
assert_property:
|
||||||
TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
|
opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4));
|
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
ast_stack.back()->children.back()->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
} |
|
} |
|
||||||
TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
|
opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
|
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
ast_stack.back()->children.back()->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
} |
|
} |
|
||||||
TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
|
opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5));
|
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
ast_stack.back()->children.back()->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
} |
|
} |
|
||||||
TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
|
opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
|
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
ast_stack.back()->children.back()->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
} |
|
} |
|
||||||
TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
|
opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4));
|
ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
ast_stack.back()->children.back()->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
} |
|
} |
|
||||||
TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
|
opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
|
||||||
if (norestrict_mode)
|
if (norestrict_mode) {
|
||||||
delete $4;
|
|
||||||
else
|
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
|
|
||||||
} |
|
|
||||||
TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
|
|
||||||
if (norestrict_mode)
|
|
||||||
delete $5;
|
delete $5;
|
||||||
else
|
} else {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
|
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
ast_stack.back()->children.back()->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} |
|
||||||
|
opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
|
||||||
|
if (norestrict_mode) {
|
||||||
|
delete $6;
|
||||||
|
} else {
|
||||||
|
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
|
||||||
|
if ($1 != nullptr) {
|
||||||
|
ast_stack.back()->children.back()->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
simple_behavioral_stmt:
|
simple_behavioral_stmt:
|
||||||
|
@ -1670,6 +1756,11 @@ case_expr_list:
|
||||||
TOK_DEFAULT {
|
TOK_DEFAULT {
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT));
|
ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT));
|
||||||
} |
|
} |
|
||||||
|
TOK_SVA_LABEL {
|
||||||
|
ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER));
|
||||||
|
ast_stack.back()->children.back()->str = *$1;
|
||||||
|
delete $1;
|
||||||
|
} |
|
||||||
expr {
|
expr {
|
||||||
ast_stack.back()->children.push_back($1);
|
ast_stack.back()->children.push_back($1);
|
||||||
} |
|
} |
|
||||||
|
|
|
@ -196,7 +196,11 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap)
|
||||||
if (log_hdump.count(header_id) && design != nullptr)
|
if (log_hdump.count(header_id) && design != nullptr)
|
||||||
for (auto &filename : log_hdump.at(header_id)) {
|
for (auto &filename : log_hdump.at(header_id)) {
|
||||||
log("Dumping current design to '%s'.\n", filename.c_str());
|
log("Dumping current design to '%s'.\n", filename.c_str());
|
||||||
|
if (yosys_xtrace)
|
||||||
|
IdString::xtrace_db_dump();
|
||||||
Pass::call(design, {"dump", "-o", filename});
|
Pass::call(design, {"dump", "-o", filename});
|
||||||
|
if (yosys_xtrace)
|
||||||
|
log("#X# -- end of dump --\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pop_errfile)
|
if (pop_errfile)
|
||||||
|
|
|
@ -86,6 +86,8 @@ Pass::pre_post_exec_state_t Pass::pre_execute()
|
||||||
|
|
||||||
void Pass::post_execute(Pass::pre_post_exec_state_t state)
|
void Pass::post_execute(Pass::pre_post_exec_state_t state)
|
||||||
{
|
{
|
||||||
|
IdString::checkpoint();
|
||||||
|
|
||||||
int64_t time_ns = PerformanceTimer::query() - state.begin_ns;
|
int64_t time_ns = PerformanceTimer::query() - state.begin_ns;
|
||||||
runtime_ns += time_ns;
|
runtime_ns += time_ns;
|
||||||
current_pass = state.parent_pass;
|
current_pass = state.parent_pass;
|
||||||
|
|
|
@ -33,6 +33,8 @@ std::vector<int> RTLIL::IdString::global_refcount_storage_;
|
||||||
std::vector<char*> RTLIL::IdString::global_id_storage_;
|
std::vector<char*> RTLIL::IdString::global_id_storage_;
|
||||||
dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_;
|
dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_;
|
||||||
std::vector<int> RTLIL::IdString::global_free_idx_list_;
|
std::vector<int> RTLIL::IdString::global_free_idx_list_;
|
||||||
|
int RTLIL::IdString::last_created_idx_[8];
|
||||||
|
int RTLIL::IdString::last_created_idx_ptr_;
|
||||||
|
|
||||||
RTLIL::Const::Const()
|
RTLIL::Const::Const()
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,6 +76,9 @@ namespace RTLIL
|
||||||
|
|
||||||
struct IdString
|
struct IdString
|
||||||
{
|
{
|
||||||
|
#undef YOSYS_XTRACE_GET_PUT
|
||||||
|
#undef YOSYS_SORT_ID_FREE_LIST
|
||||||
|
|
||||||
// the global id string cache
|
// the global id string cache
|
||||||
|
|
||||||
static struct destruct_guard_t {
|
static struct destruct_guard_t {
|
||||||
|
@ -89,9 +92,43 @@ namespace RTLIL
|
||||||
static dict<char*, int, hash_cstr_ops> global_id_index_;
|
static dict<char*, int, hash_cstr_ops> global_id_index_;
|
||||||
static std::vector<int> global_free_idx_list_;
|
static std::vector<int> global_free_idx_list_;
|
||||||
|
|
||||||
|
static int last_created_idx_ptr_;
|
||||||
|
static int last_created_idx_[8];
|
||||||
|
|
||||||
|
static inline void xtrace_db_dump()
|
||||||
|
{
|
||||||
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
|
for (int idx = 0; idx < GetSize(global_id_storage_); idx++)
|
||||||
|
{
|
||||||
|
if (global_id_storage_.at(idx) == nullptr)
|
||||||
|
log("#X# DB-DUMP index %d: FREE\n", idx);
|
||||||
|
else
|
||||||
|
log("#X# DB-DUMP index %d: '%s' (ref %d)\n", idx, global_id_storage_.at(idx), global_refcount_storage_.at(idx));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void checkpoint()
|
||||||
|
{
|
||||||
|
last_created_idx_ptr_ = 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (last_created_idx_[i])
|
||||||
|
put_reference(last_created_idx_[i]);
|
||||||
|
last_created_idx_[i] = 0;
|
||||||
|
}
|
||||||
|
#ifdef YOSYS_SORT_ID_FREE_LIST
|
||||||
|
std::sort(global_free_idx_list_.begin(), global_free_idx_list_.end(), std::greater<int>());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline int get_reference(int idx)
|
static inline int get_reference(int idx)
|
||||||
{
|
{
|
||||||
global_refcount_storage_.at(idx)++;
|
global_refcount_storage_.at(idx)++;
|
||||||
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
|
if (yosys_xtrace) {
|
||||||
|
log("#X# GET-BY-INDEX '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +144,11 @@ namespace RTLIL
|
||||||
auto it = global_id_index_.find((char*)p);
|
auto it = global_id_index_.find((char*)p);
|
||||||
if (it != global_id_index_.end()) {
|
if (it != global_id_index_.end()) {
|
||||||
global_refcount_storage_.at(it->second)++;
|
global_refcount_storage_.at(it->second)++;
|
||||||
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
|
if (yosys_xtrace) {
|
||||||
|
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(it->second), it->second, global_refcount_storage_.at(it->second));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,16 +166,22 @@ namespace RTLIL
|
||||||
global_refcount_storage_.at(idx)++;
|
global_refcount_storage_.at(idx)++;
|
||||||
|
|
||||||
// Avoid Create->Delete->Create pattern
|
// Avoid Create->Delete->Create pattern
|
||||||
static IdString last_created_id;
|
if (last_created_idx_[last_created_idx_ptr_])
|
||||||
put_reference(last_created_id.index_);
|
put_reference(last_created_idx_[last_created_idx_ptr_]);
|
||||||
last_created_id.index_ = idx;
|
last_created_idx_[last_created_idx_ptr_] = idx;
|
||||||
get_reference(last_created_id.index_);
|
get_reference(last_created_idx_[last_created_idx_ptr_]);
|
||||||
|
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
|
||||||
|
|
||||||
if (yosys_xtrace) {
|
if (yosys_xtrace) {
|
||||||
log("#X# New IdString '%s' with index %d.\n", p, idx);
|
log("#X# New IdString '%s' with index %d.\n", p, idx);
|
||||||
log_backtrace("-X- ", yosys_xtrace-1);
|
log_backtrace("-X- ", yosys_xtrace-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
|
if (yosys_xtrace) {
|
||||||
|
log("#X# GET-BY-NAME '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +192,12 @@ namespace RTLIL
|
||||||
if (!destruct_guard.ok)
|
if (!destruct_guard.ok)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef YOSYS_XTRACE_GET_PUT
|
||||||
|
if (yosys_xtrace) {
|
||||||
|
log("#X# PUT '%s' (index %d, refcount %d)\n", global_id_storage_.at(idx), idx, global_refcount_storage_.at(idx));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
log_assert(global_refcount_storage_.at(idx) > 0);
|
log_assert(global_refcount_storage_.at(idx) > 0);
|
||||||
|
|
||||||
if (--global_refcount_storage_.at(idx) != 0)
|
if (--global_refcount_storage_.at(idx) != 0)
|
||||||
|
@ -1282,7 +1336,7 @@ inline bool RTLIL::SigBit::operator<(const RTLIL::SigBit &other) const {
|
||||||
return wire ? (offset < other.offset) : (data < other.data);
|
return wire ? (offset < other.offset) : (data < other.data);
|
||||||
if (wire != nullptr && other.wire != nullptr)
|
if (wire != nullptr && other.wire != nullptr)
|
||||||
return wire->name < other.wire->name;
|
return wire->name < other.wire->name;
|
||||||
return wire < other.wire;
|
return (wire != nullptr) < (other.wire != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const {
|
inline bool RTLIL::SigBit::operator==(const RTLIL::SigBit &other) const {
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32)
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
@ -41,13 +41,15 @@
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <dirent.h>
|
# include <dirent.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <glob.h>
|
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <dirent.h>
|
# include <dirent.h>
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/wait.h>
|
# include <sys/wait.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_WIN32) && defined(YOSYS_ENABLE_GLOB)
|
||||||
# include <glob.h>
|
# include <glob.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -216,12 +218,18 @@ std::string next_token(std::string &text, const char *sep, bool long_strings)
|
||||||
|
|
||||||
if (long_strings && pos_begin != text.size() && text[pos_begin] == '"') {
|
if (long_strings && pos_begin != text.size() && text[pos_begin] == '"') {
|
||||||
string sep_string = sep;
|
string sep_string = sep;
|
||||||
for (size_t i = pos_begin+1; i < text.size(); i++)
|
for (size_t i = pos_begin+1; i < text.size(); i++) {
|
||||||
if (text[i] == '"' && (i+1 == text.size() || sep_string.find(text[i+1]) != std::string::npos)) {
|
if (text[i] == '"' && (i+1 == text.size() || sep_string.find(text[i+1]) != std::string::npos)) {
|
||||||
std::string token = text.substr(pos_begin, i-pos_begin+1);
|
std::string token = text.substr(pos_begin, i-pos_begin+1);
|
||||||
text = text.substr(i+1);
|
text = text.substr(i+1);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
if (i+1 < text.size() && text[i] == '"' && text[i+1] == ';' && (i+2 == text.size() || sep_string.find(text[i+2]) != std::string::npos)) {
|
||||||
|
std::string token = text.substr(pos_begin, i-pos_begin+1);
|
||||||
|
text = text.substr(i+2);
|
||||||
|
return token + ";";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t pos_end = text.find_first_of(sep, pos_begin);
|
size_t pos_end = text.find_first_of(sep, pos_begin);
|
||||||
|
@ -564,7 +572,7 @@ std::vector<std::string> glob_filename(const std::string &filename_pattern)
|
||||||
{
|
{
|
||||||
std::vector<std::string> results;
|
std::vector<std::string> results;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32) || !defined(YOSYS_ENABLE_GLOB)
|
||||||
results.push_back(filename_pattern);
|
results.push_back(filename_pattern);
|
||||||
#else
|
#else
|
||||||
glob_t globbuf;
|
glob_t globbuf;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
//
|
//
|
||||||
// yosys -- Yosys Open SYnthesis Suite
|
// yosys -- Yosys Open SYnthesis Suite
|
||||||
//
|
//
|
||||||
// Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
|
// Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
// copyright notice and this permission notice appear in all copies.
|
// copyright notice and this permission notice appear in all copies.
|
||||||
//
|
//
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
@ -73,7 +73,7 @@ message Module {
|
||||||
BitVector bits = 2;
|
BitVector bits = 2;
|
||||||
}
|
}
|
||||||
map<string, Port> port = 2;
|
map<string, Port> port = 2;
|
||||||
|
|
||||||
// Named cells in this module.
|
// Named cells in this module.
|
||||||
message Cell {
|
message Cell {
|
||||||
// Set to true when the name of this cell is automatically created and
|
// Set to true when the name of this cell is automatically created and
|
||||||
|
@ -129,7 +129,7 @@ message Model {
|
||||||
TYPE_FALSE = 6;
|
TYPE_FALSE = 6;
|
||||||
};
|
};
|
||||||
Type type = 1;
|
Type type = 1;
|
||||||
|
|
||||||
message Port {
|
message Port {
|
||||||
// Name of port.
|
// Name of port.
|
||||||
string portname = 1;
|
string portname = 1;
|
||||||
|
@ -148,7 +148,7 @@ message Model {
|
||||||
// Set for AND, NAND.
|
// Set for AND, NAND.
|
||||||
Gate gate = 3;
|
Gate gate = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set when the node drives given output port(s).
|
// Set when the node drives given output port(s).
|
||||||
message OutPort {
|
message OutPort {
|
||||||
// Name of port.
|
// Name of port.
|
||||||
|
|
|
@ -910,7 +910,7 @@ struct HierarchyPass : public Pass {
|
||||||
if (m == nullptr)
|
if (m == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty()) {
|
if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
|
||||||
IdString new_m_name = m->derive(design, cell->parameters, true);
|
IdString new_m_name = m->derive(design, cell->parameters, true);
|
||||||
if (new_m_name.empty())
|
if (new_m_name.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct WreduceWorker
|
||||||
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
|
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
|
||||||
std::set<SigBit> work_queue_bits;
|
std::set<SigBit> work_queue_bits;
|
||||||
pool<SigBit> keep_bits;
|
pool<SigBit> keep_bits;
|
||||||
|
dict<SigBit, State> init_bits;
|
||||||
|
|
||||||
WreduceWorker(WreduceConfig *config, Module *module) :
|
WreduceWorker(WreduceConfig *config, Module *module) :
|
||||||
config(config), module(module), mi(module) { }
|
config(config), module(module), mi(module) { }
|
||||||
|
@ -141,6 +142,7 @@ struct WreduceWorker
|
||||||
|
|
||||||
SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
|
SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
|
||||||
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
|
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
|
||||||
|
Const initval;
|
||||||
|
|
||||||
int width_before = GetSize(sig_q);
|
int width_before = GetSize(sig_q);
|
||||||
|
|
||||||
|
@ -150,16 +152,24 @@ struct WreduceWorker
|
||||||
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
|
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
|
||||||
bool sign_ext = !zero_ext;
|
bool sign_ext = !zero_ext;
|
||||||
|
|
||||||
|
for (int i = 0; i < GetSize(sig_q); i++) {
|
||||||
|
SigBit bit = sig_q[i];
|
||||||
|
if (init_bits.count(bit))
|
||||||
|
initval.bits.push_back(init_bits.at(bit));
|
||||||
|
else
|
||||||
|
initval.bits.push_back(State::Sx);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = GetSize(sig_q)-1; i >= 0; i--)
|
for (int i = GetSize(sig_q)-1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (zero_ext && sig_d[i] == State::S0) {
|
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) {
|
||||||
module->connect(sig_q[i], State::S0);
|
module->connect(sig_q[i], State::S0);
|
||||||
sig_d.remove(i);
|
sig_d.remove(i);
|
||||||
sig_q.remove(i);
|
sig_q.remove(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) {
|
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) {
|
||||||
module->connect(sig_q[i], sig_q[i-1]);
|
module->connect(sig_q[i], sig_q[i-1]);
|
||||||
sig_d.remove(i);
|
sig_d.remove(i);
|
||||||
sig_q.remove(i);
|
sig_q.remove(i);
|
||||||
|
@ -167,7 +177,7 @@ struct WreduceWorker
|
||||||
}
|
}
|
||||||
|
|
||||||
auto info = mi.query(sig_q[i]);
|
auto info = mi.query(sig_q[i]);
|
||||||
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
|
if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
|
||||||
sig_d.remove(i);
|
sig_d.remove(i);
|
||||||
sig_q.remove(i);
|
sig_q.remove(i);
|
||||||
zero_ext = false;
|
zero_ext = false;
|
||||||
|
@ -183,10 +193,11 @@ struct WreduceWorker
|
||||||
|
|
||||||
if (GetSize(sig_q) == 0) {
|
if (GetSize(sig_q) == 0) {
|
||||||
log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
|
log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
|
||||||
|
module->remove(cell);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
|
log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
|
||||||
log_id(module), log_id(cell), log_id(cell->type));
|
log_id(module), log_id(cell), log_id(cell->type));
|
||||||
|
|
||||||
for (auto bit : sig_d)
|
for (auto bit : sig_d)
|
||||||
|
@ -376,10 +387,18 @@ struct WreduceWorker
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
for (auto w : module->wires())
|
for (auto w : module->wires()) {
|
||||||
if (w->get_bool_attribute("\\keep"))
|
if (w->get_bool_attribute("\\keep"))
|
||||||
for (auto bit : mi.sigmap(w))
|
for (auto bit : mi.sigmap(w))
|
||||||
keep_bits.insert(bit);
|
keep_bits.insert(bit);
|
||||||
|
if (w->attributes.count("\\init")) {
|
||||||
|
Const initval = w->attributes.at("\\init");
|
||||||
|
SigSpec initsig = mi.sigmap(w);
|
||||||
|
int width = std::min(GetSize(initval), GetSize(initsig));
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
init_bits[initsig[i]] = initval[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto c : module->selected_cells())
|
for (auto c : module->selected_cells())
|
||||||
work_queue_cells.insert(c);
|
work_queue_cells.insert(c);
|
||||||
|
|
|
@ -4,5 +4,5 @@ passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
|
||||||
EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
|
EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h
|
||||||
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
|
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
|
||||||
|
|
||||||
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/ice40_dsp.pmg passes/pmgen/pmgen.py
|
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
|
||||||
$(P) cd passes/pmgen && python3 pmgen.py ice40_dsp
|
$(P) mkdir -p passes/pmgen && python3 $^ $@
|
||||||
|
|
|
@ -16,7 +16,7 @@ API of Generated Matcher
|
||||||
========================
|
========================
|
||||||
|
|
||||||
When `pmgen.py` reads a `foobar.pmg` file, it writes `foobar_pm.h` containing
|
When `pmgen.py` reads a `foobar.pmg` file, it writes `foobar_pm.h` containing
|
||||||
a class `foobar_pm`. That class is instanciated with an RTLIL module and a
|
a class `foobar_pm`. That class is instantiated with an RTLIL module and a
|
||||||
list of cells from that module:
|
list of cells from that module:
|
||||||
|
|
||||||
foobar_pm pm(module, module->selected_cells());
|
foobar_pm pm(module, module->selected_cells());
|
||||||
|
@ -142,7 +142,7 @@ The `select` lines are evaluated once for each cell when the matcher is
|
||||||
initialized. A `match` block will only consider cells for which all `select`
|
initialized. A `match` block will only consider cells for which all `select`
|
||||||
expressions evaluated to `true`. Note that the state variable corresponding to
|
expressions evaluated to `true`. Note that the state variable corresponding to
|
||||||
the match (in the example `mul`) is the only state variable that may be used
|
the match (in the example `mul`) is the only state variable that may be used
|
||||||
`select` lines.
|
in `select` lines.
|
||||||
|
|
||||||
Index lines are using the `index <type> expr1 === expr2` syntax. `expr1` is
|
Index lines are using the `index <type> expr1 === expr2` syntax. `expr1` is
|
||||||
evaluated during matcher initialization and the same restrictions apply as for
|
evaluated during matcher initialization and the same restrictions apply as for
|
||||||
|
|
|
@ -6,7 +6,11 @@ import pprint
|
||||||
|
|
||||||
pp = pprint.PrettyPrinter(indent=4)
|
pp = pprint.PrettyPrinter(indent=4)
|
||||||
|
|
||||||
prefix = sys.argv[1]
|
pmgfile = sys.argv[1]
|
||||||
|
assert pmgfile.endswith(".pmg")
|
||||||
|
prefix = pmgfile[0:-4]
|
||||||
|
prefix = prefix.split('/')[-1]
|
||||||
|
outfile = sys.argv[2]
|
||||||
|
|
||||||
state_types = dict()
|
state_types = dict()
|
||||||
udata_types = dict()
|
udata_types = dict()
|
||||||
|
@ -73,7 +77,7 @@ def rewrite_cpp(s):
|
||||||
|
|
||||||
return "".join(t)
|
return "".join(t)
|
||||||
|
|
||||||
with open("%s.pmg" % prefix, "r") as f:
|
with open(pmgfile, "r") as f:
|
||||||
while True:
|
while True:
|
||||||
line = f.readline()
|
line = f.readline()
|
||||||
if line == "": break
|
if line == "": break
|
||||||
|
@ -82,7 +86,7 @@ with open("%s.pmg" % prefix, "r") as f:
|
||||||
cmd = line.split()
|
cmd = line.split()
|
||||||
if len(cmd) == 0 or cmd[0].startswith("//"): continue
|
if len(cmd) == 0 or cmd[0].startswith("//"): continue
|
||||||
cmd = cmd[0]
|
cmd = cmd[0]
|
||||||
|
|
||||||
if cmd == "state":
|
if cmd == "state":
|
||||||
m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line)
|
m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line)
|
||||||
assert m
|
assert m
|
||||||
|
@ -176,7 +180,7 @@ with open("%s.pmg" % prefix, "r") as f:
|
||||||
|
|
||||||
blocks.append(block)
|
blocks.append(block)
|
||||||
|
|
||||||
with open("%s_pm.h" % prefix, "w") as f:
|
with open(outfile, "w") as f:
|
||||||
print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f)
|
print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f)
|
||||||
print("", file=f)
|
print("", file=f)
|
||||||
|
|
||||||
|
|
|
@ -8,4 +8,5 @@ OBJS += passes/sat/expose.o
|
||||||
OBJS += passes/sat/assertpmux.o
|
OBJS += passes/sat/assertpmux.o
|
||||||
OBJS += passes/sat/clk2fflogic.o
|
OBJS += passes/sat/clk2fflogic.o
|
||||||
OBJS += passes/sat/async2sync.o
|
OBJS += passes/sat/async2sync.o
|
||||||
|
OBJS += passes/sat/supercover.o
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct Async2syncPass : public Pass {
|
||||||
log("reset value in the next cycle regardless of the data-in value at the time of\n");
|
log("reset value in the next cycle regardless of the data-in value at the time of\n");
|
||||||
log("the clock edge.\n");
|
log("the clock edge.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("Currently only $adff cells are supported by this pass.\n");
|
log("Currently only $adff and $dffsr cells are supported by this pass.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
@ -84,7 +84,7 @@ struct Async2syncPass : public Pass {
|
||||||
bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool();
|
bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool();
|
||||||
Const arst_val = cell->parameters["\\ARST_VALUE"];
|
Const arst_val = cell->parameters["\\ARST_VALUE"];
|
||||||
|
|
||||||
SigSpec sig_clk = cell->getPort("\\CLK");
|
// SigSpec sig_clk = cell->getPort("\\CLK");
|
||||||
SigSpec sig_arst = cell->getPort("\\ARST");
|
SigSpec sig_arst = cell->getPort("\\ARST");
|
||||||
SigSpec sig_d = cell->getPort("\\D");
|
SigSpec sig_d = cell->getPort("\\D");
|
||||||
SigSpec sig_q = cell->getPort("\\Q");
|
SigSpec sig_q = cell->getPort("\\Q");
|
||||||
|
@ -120,6 +120,55 @@ struct Async2syncPass : public Pass {
|
||||||
cell->type = "$dff";
|
cell->type = "$dff";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cell->type.in("$dffsr"))
|
||||||
|
{
|
||||||
|
// bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool();
|
||||||
|
bool set_pol = cell->parameters["\\SET_POLARITY"].as_bool();
|
||||||
|
bool clr_pol = cell->parameters["\\CLR_POLARITY"].as_bool();
|
||||||
|
|
||||||
|
// SigSpec sig_clk = cell->getPort("\\CLK");
|
||||||
|
SigSpec sig_set = cell->getPort("\\SET");
|
||||||
|
SigSpec sig_clr = cell->getPort("\\CLR");
|
||||||
|
SigSpec sig_d = cell->getPort("\\D");
|
||||||
|
SigSpec sig_q = cell->getPort("\\Q");
|
||||||
|
|
||||||
|
log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n",
|
||||||
|
log_id(module), log_id(cell), log_id(cell->type),
|
||||||
|
log_signal(sig_set), log_signal(sig_clr), log_signal(sig_d), log_signal(sig_q));
|
||||||
|
|
||||||
|
Const init_val;
|
||||||
|
for (int i = 0; i < GetSize(sig_q); i++) {
|
||||||
|
SigBit bit = sigmap(sig_q[i]);
|
||||||
|
init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx);
|
||||||
|
del_initbits.insert(bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d));
|
||||||
|
Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q));
|
||||||
|
new_q->attributes["\\init"] = init_val;
|
||||||
|
|
||||||
|
if (!set_pol)
|
||||||
|
sig_set = module->Not(NEW_ID, sig_set);
|
||||||
|
|
||||||
|
if (clr_pol)
|
||||||
|
sig_clr = module->Not(NEW_ID, sig_clr);
|
||||||
|
|
||||||
|
SigSpec tmp = module->Or(NEW_ID, sig_d, sig_set);
|
||||||
|
module->addAnd(NEW_ID, tmp, sig_clr, new_d);
|
||||||
|
|
||||||
|
tmp = module->Or(NEW_ID, new_q, sig_set);
|
||||||
|
module->addAnd(NEW_ID, tmp, sig_clr, sig_q);
|
||||||
|
|
||||||
|
cell->setPort("\\D", new_d);
|
||||||
|
cell->setPort("\\Q", new_q);
|
||||||
|
cell->unsetPort("\\SET");
|
||||||
|
cell->unsetPort("\\CLR");
|
||||||
|
cell->unsetParam("\\SET_POLARITY");
|
||||||
|
cell->unsetParam("\\CLR_POLARITY");
|
||||||
|
cell->type = "$dff";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* 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 SupercoverPass : public Pass {
|
||||||
|
SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" supercover [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("This command adds two cover cells for each bit of each selected wire, one\n");
|
||||||
|
log("checking for a hi signal level and one checking for lo level.\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// bool flag_noinit = false;
|
||||||
|
|
||||||
|
log_header(design, "Executing SUPERCOVER pass.\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
{
|
||||||
|
// if (args[argidx] == "-noinit") {
|
||||||
|
// flag_noinit = true;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
pool<SigBit> handled_bits;
|
||||||
|
|
||||||
|
int cnt_wire = 0, cnt_bits = 0;
|
||||||
|
log("Adding cover cells to module %s.\n", log_id(module));
|
||||||
|
for (auto wire : module->selected_wires())
|
||||||
|
{
|
||||||
|
bool counted_wire = false;
|
||||||
|
std::string src = wire->get_src_attribute();
|
||||||
|
|
||||||
|
for (auto bit : sigmap(SigSpec(wire)))
|
||||||
|
{
|
||||||
|
if (bit.wire == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (handled_bits.count(bit))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SigSpec inv = module->Not(NEW_ID, bit);
|
||||||
|
module->addCover(NEW_ID, bit, State::S1, src);
|
||||||
|
module->addCover(NEW_ID, inv, State::S1, src);
|
||||||
|
|
||||||
|
handled_bits.insert(bit);
|
||||||
|
if (!counted_wire) {
|
||||||
|
counted_wire = false;
|
||||||
|
cnt_wire++;
|
||||||
|
}
|
||||||
|
cnt_bits++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log(" added cover cells to %d wires, %d bits.\n", cnt_wire, cnt_bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} SupercoverPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -660,8 +660,8 @@ struct DfflibmapPass : public Pass {
|
||||||
map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_");
|
map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_");
|
||||||
map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_");
|
map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_");
|
||||||
|
|
||||||
log(" final dff cell mappings:\n");
|
log(" final dff cell mappings:\n");
|
||||||
logmap_all();
|
logmap_all();
|
||||||
|
|
||||||
for (auto &it : design->modules_)
|
for (auto &it : design->modules_)
|
||||||
if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox"))
|
if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox"))
|
||||||
|
|
|
@ -132,9 +132,9 @@ static void dump_dot_graph(string filename,
|
||||||
pool<RTLIL::SigBit> nodes, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges,
|
pool<RTLIL::SigBit> nodes, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges,
|
||||||
pool<RTLIL::SigBit> inputs, pool<RTLIL::SigBit> outputs,
|
pool<RTLIL::SigBit> inputs, pool<RTLIL::SigBit> outputs,
|
||||||
std::function<GraphStyle(RTLIL::SigBit)> node_style =
|
std::function<GraphStyle(RTLIL::SigBit)> node_style =
|
||||||
[](RTLIL::SigBit) { return GraphStyle{}; },
|
[](RTLIL::SigBit) { return GraphStyle{}; },
|
||||||
std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style =
|
std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style =
|
||||||
[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; },
|
[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; },
|
||||||
string name = "")
|
string name = "")
|
||||||
{
|
{
|
||||||
FILE *f = fopen(filename.c_str(), "w");
|
FILE *f = fopen(filename.c_str(), "w");
|
||||||
|
|
|
@ -30,7 +30,7 @@ endmodule
|
||||||
module PADOUT (output padout, input padin, input oe);
|
module PADOUT (output padout, input padin, input oe);
|
||||||
assign padout = padin;
|
assign padout = padin;
|
||||||
assign oe = oe;
|
assign oe = oe;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module LUT4 (output dout,
|
module LUT4 (output dout,
|
||||||
input din0, din1, din2, din3);
|
input din0, din1, din2, din3);
|
||||||
|
@ -66,14 +66,14 @@ always @(dataa_w or datab_w or datac_w or datad_w) begin
|
||||||
datac_w, datad_w);
|
datac_w, datad_w);
|
||||||
end
|
end
|
||||||
assign dout = combout_rt & 1'b1;
|
assign dout = combout_rt & 1'b1;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module DFF (output q,
|
module DFF (output q,
|
||||||
input d, ck);
|
input d, ck);
|
||||||
reg q;
|
reg q;
|
||||||
always @(posedge ck)
|
always @(posedge ck)
|
||||||
q <= d;
|
q <= d;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,13 +52,13 @@ struct AnlogicEqnPass : public Pass {
|
||||||
eqn += names[j];
|
eqn += names[j];
|
||||||
else
|
else
|
||||||
eqn += std::string("~") + names[j];
|
eqn += std::string("~") + names[j];
|
||||||
|
|
||||||
if (j!=(inputs-1)) eqn += "*";
|
if (j!=(inputs-1)) eqn += "*";
|
||||||
}
|
}
|
||||||
eqn += ")+";
|
eqn += ")+";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (eqn.empty()) return Const("0");
|
if (eqn.empty()) return Const("0");
|
||||||
eqn = eqn.substr(0, eqn.length()-1);
|
eqn = eqn.substr(0, eqn.length()-1);
|
||||||
return Const(eqn);
|
return Const(eqn);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
OBJS += techlibs/ecp5/synth_ecp5.o
|
OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
|
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
|
||||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
|
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
|
||||||
|
|
|
@ -33,7 +33,7 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO);
|
||||||
input CI, BI;
|
input CI, BI;
|
||||||
output [Y_WIDTH-1:0] CO;
|
output [Y_WIDTH-1:0] CO;
|
||||||
|
|
||||||
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
|
||||||
|
|
||||||
wire [Y_WIDTH-1:0] A_buf, B_buf;
|
wire [Y_WIDTH-1:0] A_buf, B_buf;
|
||||||
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
|
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
|
||||||
|
|
|
@ -156,6 +156,41 @@ module OSCG(
|
||||||
parameter DIV = 128;
|
parameter DIV = 128;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *) (* keep *)
|
||||||
|
module USRMCLK(
|
||||||
|
input USRMCLKI, USRMCLKTS,
|
||||||
|
output USRMCLKO
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *) (* keep *)
|
||||||
|
module JTAGG(
|
||||||
|
input TCK, TMS, TDI, JTDO2, JTDO1,
|
||||||
|
output TDO, JTDI, JTCK, JRTI2, JRTI1,
|
||||||
|
output JSHIFT, JUPDATE, JRSTN, JCE2, JCE1
|
||||||
|
);
|
||||||
|
parameter ER1 = "ENABLED";
|
||||||
|
parameter ER2 = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module DELAYF(
|
||||||
|
input A, LOADN, MOVE, DIRECTION,
|
||||||
|
output Z, CFLAG
|
||||||
|
);
|
||||||
|
parameter DEL_MODE = "USER_DEFINED";
|
||||||
|
parameter DEL_VALUE = 0;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module DELAYG(
|
||||||
|
input A,
|
||||||
|
output Z
|
||||||
|
);
|
||||||
|
parameter DEL_MODE = "USER_DEFINED";
|
||||||
|
parameter DEL_VALUE = 0;
|
||||||
|
endmodule
|
||||||
|
|
||||||
(* blackbox *)
|
(* blackbox *)
|
||||||
module IDDRX1F(
|
module IDDRX1F(
|
||||||
input D, SCLK, RST,
|
input D, SCLK, RST,
|
||||||
|
@ -164,6 +199,31 @@ module IDDRX1F(
|
||||||
parameter GSR = "ENABLED";
|
parameter GSR = "ENABLED";
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module IDDRX2F(
|
||||||
|
input D, SCLK, ECLK, RST,
|
||||||
|
output Q0, Q1, Q2, Q3
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module IDDR71B(
|
||||||
|
input D, SCLK, ECLK, RST, ALIGNWD,
|
||||||
|
output Q0, Q1, Q2, Q3, Q4, Q5, Q6
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module IDDRX2DQA(
|
||||||
|
input D, DQSR90, ECLK, SCLK, RST,
|
||||||
|
input RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0,
|
||||||
|
output Q0, Q1, Q2, Q3, QWL
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
(* blackbox *)
|
(* blackbox *)
|
||||||
module ODDRX1F(
|
module ODDRX1F(
|
||||||
input SCLK, RST, D0, D1,
|
input SCLK, RST, D0, D1,
|
||||||
|
@ -172,6 +232,91 @@ module ODDRX1F(
|
||||||
parameter GSR = "ENABLED";
|
parameter GSR = "ENABLED";
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module ODDRX2F(
|
||||||
|
input SCLK, ECLK, RST, D0, D1, D2, D3,
|
||||||
|
output Q
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module ODDR71B(
|
||||||
|
input SCLK, ECLK, RST, D0, D1, D2, D3, D4, D5, D6,
|
||||||
|
output Q
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module OSHX2A(
|
||||||
|
input D0, D1, RST, ECLK, SCLK,
|
||||||
|
output Q
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module ODDRX2DQA(
|
||||||
|
input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW270,
|
||||||
|
output Q
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module ODDRX2DQSB(
|
||||||
|
input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW,
|
||||||
|
output Q
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module TSHX2DQA(
|
||||||
|
input T0, T1, SCLK, ECLK, DQSW270, RST,
|
||||||
|
output Q
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
parameter REGSET = "SET";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module TSHX2DQSA(
|
||||||
|
input T0, T1, SCLK, ECLK, DQSW, RST,
|
||||||
|
output Q
|
||||||
|
);
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
parameter REGSET = "SET";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module DQSBUFM(
|
||||||
|
input DQSI, READ1, READ0, READCLKSEL2, READCLKSEL1, READCLKSEL0, DDRDEL,
|
||||||
|
input ECLK, SCLK,
|
||||||
|
input DYNDELAY7, DYNDELAY6, DYNDELAY5, DYNDELAY4,
|
||||||
|
input DYNDELAY3, DYNDELAY2, DYNDELAY1, DYNDELAY0,
|
||||||
|
input RST, RDLOADN, RDMOVE, RDDIRECTION, WRLOADN, WRMOVE, WRDIRECTION, PAUSE,
|
||||||
|
output DQSR90, DQSW, DQSW270,
|
||||||
|
output RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0,
|
||||||
|
output DATAVALID, BURSTDET, RDCFLAG, WRCFLAG
|
||||||
|
);
|
||||||
|
parameter DQS_LI_DEL_ADJ = "FACTORYONLY";
|
||||||
|
parameter DQS_LI_DEL_VAL = 0;
|
||||||
|
parameter DQS_LO_DEL_ADJ = "FACTORYONLY";
|
||||||
|
parameter DQS_LO_DEL_VAL = 0;
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module DDRDLLA(
|
||||||
|
input CLK, RST, UDDCNTLN, FREEZE,
|
||||||
|
output LOCK, DDRDEL, DCNTL7, DCNTL6, DCNTL5, DCNTL4, DCNTL3, DCNTL2, DCNTL1, DCNTL0
|
||||||
|
);
|
||||||
|
parameter FORCE_MAX_DELAY = "NO";
|
||||||
|
parameter GSR = "ENABLED";
|
||||||
|
endmodule
|
||||||
|
|
||||||
(* blackbox *)
|
(* blackbox *)
|
||||||
module CLKDIVF(
|
module CLKDIVF(
|
||||||
input CLKI, RST, ALIGNWD,
|
input CLKI, RST, ALIGNWD,
|
||||||
|
@ -181,6 +326,13 @@ module CLKDIVF(
|
||||||
parameter DIV = "2.0";
|
parameter DIV = "2.0";
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
(* blackbox *)
|
||||||
|
module ECLKSYNCB(
|
||||||
|
input ECLKI, STOP,
|
||||||
|
output ECLKO
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
(* blackbox *)
|
(* blackbox *)
|
||||||
module DCCA(
|
module DCCA(
|
||||||
input CLKI, CE,
|
input CLKI, CE,
|
||||||
|
|
|
@ -47,6 +47,9 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"
|
||||||
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
|
// For Diamond compatibility, FIXME: add all Diamond flipflop mappings
|
||||||
|
module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
|
||||||
|
|
||||||
`ifndef NO_LUT
|
`ifndef NO_LUT
|
||||||
module \$lut (A, Y);
|
module \$lut (A, Y);
|
||||||
parameter WIDTH = 0;
|
parameter WIDTH = 0;
|
||||||
|
|
|
@ -57,7 +57,7 @@ module TRELLIS_RAM16X2 (
|
||||||
input RAD0, RAD1, RAD2, RAD3,
|
input RAD0, RAD1, RAD2, RAD3,
|
||||||
output DO0, DO1
|
output DO0, DO1
|
||||||
);
|
);
|
||||||
parameter WCKMUX = "WCK";
|
parameter WCKMUX = "WCK";
|
||||||
parameter WREMUX = "WRE";
|
parameter WREMUX = "WRE";
|
||||||
parameter INITVAL_0 = 16'h0000;
|
parameter INITVAL_0 = 16'h0000;
|
||||||
parameter INITVAL_1 = 16'h0000;
|
parameter INITVAL_1 = 16'h0000;
|
||||||
|
@ -104,7 +104,7 @@ module TRELLIS_DPR16X4 (
|
||||||
input [3:0] RAD,
|
input [3:0] RAD,
|
||||||
output [3:0] DO
|
output [3:0] DO
|
||||||
);
|
);
|
||||||
parameter WCKMUX = "WCK";
|
parameter WCKMUX = "WCK";
|
||||||
parameter WREMUX = "WRE";
|
parameter WREMUX = "WRE";
|
||||||
parameter [63:0] INITVAL = 64'h0000000000000000;
|
parameter [63:0] INITVAL = 64'h0000000000000000;
|
||||||
|
|
||||||
|
@ -203,13 +203,14 @@ endmodule
|
||||||
|
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
|
|
||||||
module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
|
module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
|
||||||
parameter GSR = "ENABLED";
|
parameter GSR = "ENABLED";
|
||||||
parameter [127:0] CEMUX = "1";
|
parameter [127:0] CEMUX = "1";
|
||||||
parameter CLKMUX = "CLK";
|
parameter CLKMUX = "CLK";
|
||||||
parameter LSRMUX = "LSR";
|
parameter LSRMUX = "LSR";
|
||||||
parameter SRMODE = "LSR_OVER_CE";
|
parameter SRMODE = "LSR_OVER_CE";
|
||||||
parameter REGSET = "RESET";
|
parameter REGSET = "RESET";
|
||||||
|
parameter [127:0] LSRMODE = "LSR";
|
||||||
|
|
||||||
reg muxce;
|
reg muxce;
|
||||||
always @(*)
|
always @(*)
|
||||||
|
@ -222,8 +223,13 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
|
||||||
|
|
||||||
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
|
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
|
||||||
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
|
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
|
||||||
|
wire srval;
|
||||||
localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
|
generate
|
||||||
|
if (LSRMODE == "PRLD")
|
||||||
|
assign srval = M;
|
||||||
|
else
|
||||||
|
assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
|
||||||
|
endgenerate
|
||||||
|
|
||||||
initial Q = srval;
|
initial Q = srval;
|
||||||
|
|
||||||
|
@ -339,6 +345,8 @@ module TRELLIS_SLICE(
|
||||||
parameter REG1_SD = "0";
|
parameter REG1_SD = "0";
|
||||||
parameter REG0_REGSET = "RESET";
|
parameter REG0_REGSET = "RESET";
|
||||||
parameter REG1_REGSET = "RESET";
|
parameter REG1_REGSET = "RESET";
|
||||||
|
parameter REG0_LSRMODE = "LSR";
|
||||||
|
parameter REG1_LSRMODE = "LSR";
|
||||||
parameter [127:0] CCU2_INJECT1_0 = "NO";
|
parameter [127:0] CCU2_INJECT1_0 = "NO";
|
||||||
parameter [127:0] CCU2_INJECT1_1 = "NO";
|
parameter [127:0] CCU2_INJECT1_1 = "NO";
|
||||||
parameter WREMUX = "WRE";
|
parameter WREMUX = "WRE";
|
||||||
|
@ -428,10 +436,11 @@ module TRELLIS_SLICE(
|
||||||
.CLKMUX(CLKMUX),
|
.CLKMUX(CLKMUX),
|
||||||
.LSRMUX(LSRMUX),
|
.LSRMUX(LSRMUX),
|
||||||
.SRMODE(SRMODE),
|
.SRMODE(SRMODE),
|
||||||
.REGSET(REG0_REGSET)
|
.REGSET(REG0_REGSET),
|
||||||
|
.LSRMODE(REG0_LSRMODE)
|
||||||
) ff_0 (
|
) ff_0 (
|
||||||
.CLK(CLK), .LSR(LSR), .CE(CE),
|
.CLK(CLK), .LSR(LSR), .CE(CE),
|
||||||
.DI(muxdi0),
|
.DI(muxdi0), .M(M0),
|
||||||
.Q(Q0)
|
.Q(Q0)
|
||||||
);
|
);
|
||||||
TRELLIS_FF #(
|
TRELLIS_FF #(
|
||||||
|
@ -440,10 +449,11 @@ module TRELLIS_SLICE(
|
||||||
.CLKMUX(CLKMUX),
|
.CLKMUX(CLKMUX),
|
||||||
.LSRMUX(LSRMUX),
|
.LSRMUX(LSRMUX),
|
||||||
.SRMODE(SRMODE),
|
.SRMODE(SRMODE),
|
||||||
.REGSET(REG1_REGSET)
|
.REGSET(REG1_REGSET),
|
||||||
|
.LSRMODE(REG1_LSRMODE)
|
||||||
) ff_1 (
|
) ff_1 (
|
||||||
.CLK(CLK), .LSR(LSR), .CE(CE),
|
.CLK(CLK), .LSR(LSR), .CE(CE),
|
||||||
.DI(muxdi1),
|
.DI(muxdi1), .M(M1),
|
||||||
.Q(Q1)
|
.Q(Q1)
|
||||||
);
|
);
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -547,3 +557,20 @@ module DP16KD(
|
||||||
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||||
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// For Diamond compatibility, FIXME: add all Diamond flipflop mappings
|
||||||
|
module FD1S3BX(input PD, D, CK, output Q);
|
||||||
|
TRELLIS_FF #(
|
||||||
|
.GSR("DISABLED"),
|
||||||
|
.CEMUX("1"),
|
||||||
|
.CLKMUX("CLK"),
|
||||||
|
.LSRMUX("LSR"),
|
||||||
|
.REGSET("SET"),
|
||||||
|
.SRMODE("ASYNC")
|
||||||
|
) tff_i (
|
||||||
|
.CLK(CK),
|
||||||
|
.LSR(PD),
|
||||||
|
.DI(D),
|
||||||
|
.Q(Q)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
|
* Copyright (C) 2018-19 David Shah <david@symbioticeda.com>
|
||||||
|
*
|
||||||
|
* 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 Ecp5FfinitPass : public Pass {
|
||||||
|
Ecp5FfinitPass() : Pass("ecp5_ffinit", "ECP5: handle FF init values") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" ecp5_ffinit [options] [selection]\n");
|
||||||
|
log("\n");
|
||||||
|
log("Remove init values for FF output signals when equal to reset value.\n");
|
||||||
|
log("If reset is not used, set the reset value to the init value, otherwise\n");
|
||||||
|
log("unmap out the reset (if not an async reset).\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing ECP5_FFINIT pass (implement FF init values).\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);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
{
|
||||||
|
log("Handling FF init values in %s.\n", log_id(module));
|
||||||
|
|
||||||
|
SigMap sigmap(module);
|
||||||
|
pool<Wire*> init_wires;
|
||||||
|
dict<SigBit, State> initbits;
|
||||||
|
dict<SigBit, SigBit> initbit_to_wire;
|
||||||
|
pool<SigBit> handled_initbits;
|
||||||
|
|
||||||
|
for (auto wire : module->selected_wires())
|
||||||
|
{
|
||||||
|
if (wire->attributes.count("\\init") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SigSpec wirebits = sigmap(wire);
|
||||||
|
Const initval = wire->attributes.at("\\init");
|
||||||
|
init_wires.insert(wire);
|
||||||
|
|
||||||
|
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
|
||||||
|
{
|
||||||
|
SigBit bit = wirebits[i];
|
||||||
|
State val = initval[i];
|
||||||
|
|
||||||
|
if (val != State::S0 && val != State::S1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (initbits.count(bit)) {
|
||||||
|
if (initbits.at(bit) != val) {
|
||||||
|
log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
|
||||||
|
log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val),
|
||||||
|
log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit)));
|
||||||
|
initbits.at(bit) = State::Sx;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
initbits[bit] = val;
|
||||||
|
initbit_to_wire[bit] = SigBit(wire, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
if (cell->type != "\\TRELLIS_FF")
|
||||||
|
continue;
|
||||||
|
SigSpec sig_d = cell->getPort("\\DI");
|
||||||
|
SigSpec sig_q = cell->getPort("\\Q");
|
||||||
|
SigSpec sig_lsr = cell->getPort("\\LSR");
|
||||||
|
|
||||||
|
if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SigBit bit_d = sigmap(sig_d[0]);
|
||||||
|
SigBit bit_q = sigmap(sig_q[0]);
|
||||||
|
|
||||||
|
std::string regset = "RESET";
|
||||||
|
if (cell->hasParam("\\REGSET"))
|
||||||
|
regset = cell->getParam("\\REGSET").decode_string();
|
||||||
|
State resetState;
|
||||||
|
if (regset == "SET")
|
||||||
|
resetState = State::S1;
|
||||||
|
else if (regset == "RESET")
|
||||||
|
resetState = State::S0;
|
||||||
|
else
|
||||||
|
log_error("FF cell %s has illegal REGSET value %s.\n",
|
||||||
|
log_id(cell), regset.c_str());
|
||||||
|
|
||||||
|
if (!initbits.count(bit_q))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
State val = initbits.at(bit_q);
|
||||||
|
|
||||||
|
if (val == State::Sx)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),
|
||||||
|
log_signal(bit_q), val != State::S0 ? '1' : '0');
|
||||||
|
// Initval is the same as the reset state. Matches hardware, nowt more to do
|
||||||
|
if (val == resetState) {
|
||||||
|
handled_initbits.insert(bit_q);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetSize(sig_lsr) >= 1 && sig_lsr[0] != State::S0) {
|
||||||
|
std::string srmode = "LSR_OVER_CE";
|
||||||
|
if (cell->hasParam("\\SRMODE"))
|
||||||
|
srmode = cell->getParam("\\SRMODE").decode_string();
|
||||||
|
if (srmode == "ASYNC") {
|
||||||
|
log("Async reset value %c for FF cell %s inconsistent with init value %c.\n",
|
||||||
|
resetState != State::S0 ? '1' : '0', log_id(cell), val != State::S0 ? '1' : '0');
|
||||||
|
} else {
|
||||||
|
SigBit bit_lsr = sigmap(sig_lsr[0]);
|
||||||
|
Wire *new_bit_d = module->addWire(NEW_ID);
|
||||||
|
if (resetState == State::S0) {
|
||||||
|
module->addAndnotGate(NEW_ID, bit_d, bit_lsr, new_bit_d);
|
||||||
|
} else {
|
||||||
|
module->addOrGate(NEW_ID, bit_d, bit_lsr, new_bit_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell->setPort("\\DI", new_bit_d);
|
||||||
|
cell->setPort("\\LSR", State::S0);
|
||||||
|
|
||||||
|
if(cell->hasPort("\\CE")) {
|
||||||
|
std::string cemux = "CE";
|
||||||
|
if (cell->hasParam("\\CEMUX"))
|
||||||
|
cemux = cell->getParam("\\CEMUX").decode_string();
|
||||||
|
SigSpec sig_ce = cell->getPort("\\CE");
|
||||||
|
if (GetSize(sig_ce) >= 1) {
|
||||||
|
SigBit bit_ce = sigmap(sig_ce[0]);
|
||||||
|
Wire *new_bit_ce = module->addWire(NEW_ID);
|
||||||
|
if (cemux == "INV")
|
||||||
|
module->addAndnotGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce);
|
||||||
|
else
|
||||||
|
module->addOrGate(NEW_ID, bit_ce, bit_lsr, new_bit_ce);
|
||||||
|
cell->setPort("\\CE", new_bit_ce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET"));
|
||||||
|
handled_initbits.insert(bit_q);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cell->setParam("\\REGSET", val != State::S0 ? Const("SET") : Const("RESET"));
|
||||||
|
handled_initbits.insert(bit_q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto wire : init_wires)
|
||||||
|
{
|
||||||
|
if (wire->attributes.count("\\init") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SigSpec wirebits = sigmap(wire);
|
||||||
|
Const &initval = wire->attributes.at("\\init");
|
||||||
|
bool remove_attribute = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) {
|
||||||
|
if (handled_initbits.count(wirebits[i]))
|
||||||
|
initval[i] = State::Sx;
|
||||||
|
else if (initval[i] != State::Sx)
|
||||||
|
remove_attribute = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remove_attribute)
|
||||||
|
wire->attributes.erase("\\init");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} Ecp5FfinitPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -255,10 +255,7 @@ struct SynthEcp5Pass : public ScriptPass
|
||||||
run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
|
run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
|
||||||
run("opt_expr -mux_undef");
|
run("opt_expr -mux_undef");
|
||||||
run("simplemap");
|
run("simplemap");
|
||||||
// TODO
|
|
||||||
#if 0
|
|
||||||
run("ecp5_ffinit");
|
run("ecp5_ffinit");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map_luts"))
|
if (check_label("map_luts"))
|
||||||
|
|
|
@ -25,24 +25,24 @@ module _80_gw1n_alu(A, B, CI, BI, X, Y, CO);
|
||||||
parameter A_WIDTH = 1;
|
parameter A_WIDTH = 1;
|
||||||
parameter B_WIDTH = 1;
|
parameter B_WIDTH = 1;
|
||||||
parameter Y_WIDTH = 1;
|
parameter Y_WIDTH = 1;
|
||||||
|
|
||||||
input [A_WIDTH-1:0] A;
|
input [A_WIDTH-1:0] A;
|
||||||
input [B_WIDTH-1:0] B;
|
input [B_WIDTH-1:0] B;
|
||||||
output [Y_WIDTH-1:0] X, Y;
|
output [Y_WIDTH-1:0] X, Y;
|
||||||
|
|
||||||
input CI, BI;
|
input CI, BI;
|
||||||
output [Y_WIDTH-1:0] CO;
|
output [Y_WIDTH-1:0] CO;
|
||||||
|
|
||||||
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
||||||
|
|
||||||
wire [Y_WIDTH-1:0] A_buf, B_buf;
|
wire [Y_WIDTH-1:0] A_buf, B_buf;
|
||||||
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
|
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
|
||||||
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
|
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
|
||||||
|
|
||||||
wire [Y_WIDTH-1:0] AA = A_buf;
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
wire [Y_WIDTH-1:0] C = {CO, CI};
|
wire [Y_WIDTH-1:0] C = {CO, CI};
|
||||||
|
|
||||||
genvar i;
|
genvar i;
|
||||||
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
|
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
|
||||||
ALU #(.ALU_MODE(32'b0))
|
ALU #(.ALU_MODE(32'b0))
|
||||||
|
|
|
@ -111,7 +111,7 @@ struct SynthGowinPass : public ScriptPass
|
||||||
if (args[argidx] == "-noflatten") {
|
if (args[argidx] == "-noflatten") {
|
||||||
flatten = false;
|
flatten = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
|
@ -112,14 +112,14 @@ module GP_OBUFT(input IN, input OE, output OUT);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module \$lut (A, Y);
|
module \$lut (A, Y);
|
||||||
parameter WIDTH = 0;
|
parameter WIDTH = 0;
|
||||||
parameter LUT = 0;
|
parameter LUT = 0;
|
||||||
|
|
||||||
input [WIDTH-1:0] A;
|
input [WIDTH-1:0] A;
|
||||||
output Y;
|
output Y;
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (WIDTH == 1) begin
|
if (WIDTH == 1) begin
|
||||||
if(LUT == 2'b01) begin
|
if(LUT == 2'b01) begin
|
||||||
GP_INV _TECHMAP_REPLACE_ (.OUT(Y), .IN(A[0]) );
|
GP_INV _TECHMAP_REPLACE_ (.OUT(Y), .IN(A[0]) );
|
||||||
end
|
end
|
||||||
|
@ -127,22 +127,22 @@ module \$lut (A, Y);
|
||||||
GP_2LUT #(.INIT({2'b00, LUT})) _TECHMAP_REPLACE_ (.OUT(Y),
|
GP_2LUT #(.INIT({2'b00, LUT})) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||||
.IN0(A[0]), .IN1(1'b0));
|
.IN0(A[0]), .IN1(1'b0));
|
||||||
end
|
end
|
||||||
end else
|
end else
|
||||||
if (WIDTH == 2) begin
|
if (WIDTH == 2) begin
|
||||||
GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||||
.IN0(A[0]), .IN1(A[1]));
|
.IN0(A[0]), .IN1(A[1]));
|
||||||
end else
|
end else
|
||||||
if (WIDTH == 3) begin
|
if (WIDTH == 3) begin
|
||||||
GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||||
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]));
|
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]));
|
||||||
end else
|
end else
|
||||||
if (WIDTH == 4) begin
|
if (WIDTH == 4) begin
|
||||||
GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||||
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3]));
|
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3]));
|
||||||
end else begin
|
end else begin
|
||||||
wire _TECHMAP_FAIL_ = 1;
|
wire _TECHMAP_FAIL_ = 1;
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP);
|
module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
OBJS += techlibs/ice40/synth_ice40.o
|
OBJS += techlibs/ice40/synth_ice40.o
|
||||||
|
OBJS += techlibs/ice40/ice40_braminit.o
|
||||||
OBJS += techlibs/ice40/ice40_ffssr.o
|
OBJS += techlibs/ice40/ice40_ffssr.o
|
||||||
OBJS += techlibs/ice40/ice40_ffinit.o
|
OBJS += techlibs/ice40/ice40_ffinit.o
|
||||||
OBJS += techlibs/ice40/ice40_opt.o
|
OBJS += techlibs/ice40/ice40_opt.o
|
||||||
|
|
|
@ -7,8 +7,8 @@ module \$__ICE40_RAM4K (
|
||||||
input [10:0] WADDR,
|
input [10:0] WADDR,
|
||||||
input [15:0] MASK, WDATA
|
input [15:0] MASK, WDATA
|
||||||
);
|
);
|
||||||
parameter integer READ_MODE = 0;
|
parameter [1:0] READ_MODE = 0;
|
||||||
parameter integer WRITE_MODE = 0;
|
parameter [1:0] WRITE_MODE = 0;
|
||||||
parameter [0:0] NEGCLK_R = 0;
|
parameter [0:0] NEGCLK_R = 0;
|
||||||
parameter [0:0] NEGCLK_W = 0;
|
parameter [0:0] NEGCLK_W = 0;
|
||||||
|
|
||||||
|
|
|
@ -326,6 +326,8 @@ module SB_RAM40_4K (
|
||||||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
|
||||||
|
parameter INIT_FILE = "";
|
||||||
|
|
||||||
`ifndef BLACKBOX
|
`ifndef BLACKBOX
|
||||||
wire [15:0] WMASK_I;
|
wire [15:0] WMASK_I;
|
||||||
wire [15:0] RMASK_I;
|
wire [15:0] RMASK_I;
|
||||||
|
@ -408,43 +410,27 @@ module SB_RAM40_4K (
|
||||||
reg [15:0] memory [0:255];
|
reg [15:0] memory [0:255];
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
for (i=0; i<16; i=i+1) begin
|
if (INIT_FILE != "")
|
||||||
`ifdef YOSYS
|
$readmemh(INIT_FILE, memory);
|
||||||
memory[ 0*16 + i] <= INIT_0[16*i +: 16];
|
else
|
||||||
memory[ 1*16 + i] <= INIT_1[16*i +: 16];
|
for (i=0; i<16; i=i+1) begin
|
||||||
memory[ 2*16 + i] <= INIT_2[16*i +: 16];
|
memory[ 0*16 + i] = INIT_0[16*i +: 16];
|
||||||
memory[ 3*16 + i] <= INIT_3[16*i +: 16];
|
memory[ 1*16 + i] = INIT_1[16*i +: 16];
|
||||||
memory[ 4*16 + i] <= INIT_4[16*i +: 16];
|
memory[ 2*16 + i] = INIT_2[16*i +: 16];
|
||||||
memory[ 5*16 + i] <= INIT_5[16*i +: 16];
|
memory[ 3*16 + i] = INIT_3[16*i +: 16];
|
||||||
memory[ 6*16 + i] <= INIT_6[16*i +: 16];
|
memory[ 4*16 + i] = INIT_4[16*i +: 16];
|
||||||
memory[ 7*16 + i] <= INIT_7[16*i +: 16];
|
memory[ 5*16 + i] = INIT_5[16*i +: 16];
|
||||||
memory[ 8*16 + i] <= INIT_8[16*i +: 16];
|
memory[ 6*16 + i] = INIT_6[16*i +: 16];
|
||||||
memory[ 9*16 + i] <= INIT_9[16*i +: 16];
|
memory[ 7*16 + i] = INIT_7[16*i +: 16];
|
||||||
memory[10*16 + i] <= INIT_A[16*i +: 16];
|
memory[ 8*16 + i] = INIT_8[16*i +: 16];
|
||||||
memory[11*16 + i] <= INIT_B[16*i +: 16];
|
memory[ 9*16 + i] = INIT_9[16*i +: 16];
|
||||||
memory[12*16 + i] <= INIT_C[16*i +: 16];
|
memory[10*16 + i] = INIT_A[16*i +: 16];
|
||||||
memory[13*16 + i] <= INIT_D[16*i +: 16];
|
memory[11*16 + i] = INIT_B[16*i +: 16];
|
||||||
memory[14*16 + i] <= INIT_E[16*i +: 16];
|
memory[12*16 + i] = INIT_C[16*i +: 16];
|
||||||
memory[15*16 + i] <= INIT_F[16*i +: 16];
|
memory[13*16 + i] = INIT_D[16*i +: 16];
|
||||||
`else
|
memory[14*16 + i] = INIT_E[16*i +: 16];
|
||||||
memory[ 0*16 + i] = INIT_0[16*i +: 16];
|
memory[15*16 + i] = INIT_F[16*i +: 16];
|
||||||
memory[ 1*16 + i] = INIT_1[16*i +: 16];
|
end
|
||||||
memory[ 2*16 + i] = INIT_2[16*i +: 16];
|
|
||||||
memory[ 3*16 + i] = INIT_3[16*i +: 16];
|
|
||||||
memory[ 4*16 + i] = INIT_4[16*i +: 16];
|
|
||||||
memory[ 5*16 + i] = INIT_5[16*i +: 16];
|
|
||||||
memory[ 6*16 + i] = INIT_6[16*i +: 16];
|
|
||||||
memory[ 7*16 + i] = INIT_7[16*i +: 16];
|
|
||||||
memory[ 8*16 + i] = INIT_8[16*i +: 16];
|
|
||||||
memory[ 9*16 + i] = INIT_9[16*i +: 16];
|
|
||||||
memory[10*16 + i] = INIT_A[16*i +: 16];
|
|
||||||
memory[11*16 + i] = INIT_B[16*i +: 16];
|
|
||||||
memory[12*16 + i] = INIT_C[16*i +: 16];
|
|
||||||
memory[13*16 + i] = INIT_D[16*i +: 16];
|
|
||||||
memory[14*16 + i] = INIT_E[16*i +: 16];
|
|
||||||
memory[15*16 + i] = INIT_F[16*i +: 16];
|
|
||||||
`endif
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge WCLK) begin
|
always @(posedge WCLK) begin
|
||||||
|
@ -504,6 +490,8 @@ module SB_RAM40_4KNR (
|
||||||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
|
||||||
|
parameter INIT_FILE = "";
|
||||||
|
|
||||||
SB_RAM40_4K #(
|
SB_RAM40_4K #(
|
||||||
.WRITE_MODE(WRITE_MODE),
|
.WRITE_MODE(WRITE_MODE),
|
||||||
.READ_MODE (READ_MODE ),
|
.READ_MODE (READ_MODE ),
|
||||||
|
@ -522,7 +510,8 @@ module SB_RAM40_4KNR (
|
||||||
.INIT_C (INIT_C ),
|
.INIT_C (INIT_C ),
|
||||||
.INIT_D (INIT_D ),
|
.INIT_D (INIT_D ),
|
||||||
.INIT_E (INIT_E ),
|
.INIT_E (INIT_E ),
|
||||||
.INIT_F (INIT_F )
|
.INIT_F (INIT_F ),
|
||||||
|
.INIT_FILE (INIT_FILE )
|
||||||
) RAM (
|
) RAM (
|
||||||
.RDATA(RDATA),
|
.RDATA(RDATA),
|
||||||
.RCLK (~RCLKN),
|
.RCLK (~RCLKN),
|
||||||
|
@ -566,6 +555,8 @@ module SB_RAM40_4KNW (
|
||||||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
|
||||||
|
parameter INIT_FILE = "";
|
||||||
|
|
||||||
SB_RAM40_4K #(
|
SB_RAM40_4K #(
|
||||||
.WRITE_MODE(WRITE_MODE),
|
.WRITE_MODE(WRITE_MODE),
|
||||||
.READ_MODE (READ_MODE ),
|
.READ_MODE (READ_MODE ),
|
||||||
|
@ -584,7 +575,8 @@ module SB_RAM40_4KNW (
|
||||||
.INIT_C (INIT_C ),
|
.INIT_C (INIT_C ),
|
||||||
.INIT_D (INIT_D ),
|
.INIT_D (INIT_D ),
|
||||||
.INIT_E (INIT_E ),
|
.INIT_E (INIT_E ),
|
||||||
.INIT_F (INIT_F )
|
.INIT_F (INIT_F ),
|
||||||
|
.INIT_FILE (INIT_FILE )
|
||||||
) RAM (
|
) RAM (
|
||||||
.RDATA(RDATA),
|
.RDATA(RDATA),
|
||||||
.RCLK (RCLK ),
|
.RCLK (RCLK ),
|
||||||
|
@ -628,6 +620,8 @@ module SB_RAM40_4KNRNW (
|
||||||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||||
|
|
||||||
|
parameter INIT_FILE = "";
|
||||||
|
|
||||||
SB_RAM40_4K #(
|
SB_RAM40_4K #(
|
||||||
.WRITE_MODE(WRITE_MODE),
|
.WRITE_MODE(WRITE_MODE),
|
||||||
.READ_MODE (READ_MODE ),
|
.READ_MODE (READ_MODE ),
|
||||||
|
@ -646,7 +640,8 @@ module SB_RAM40_4KNRNW (
|
||||||
.INIT_C (INIT_C ),
|
.INIT_C (INIT_C ),
|
||||||
.INIT_D (INIT_D ),
|
.INIT_D (INIT_D ),
|
||||||
.INIT_E (INIT_E ),
|
.INIT_E (INIT_E ),
|
||||||
.INIT_F (INIT_F )
|
.INIT_F (INIT_F ),
|
||||||
|
.INIT_FILE (INIT_FILE )
|
||||||
) RAM (
|
) RAM (
|
||||||
.RDATA(RDATA),
|
.RDATA(RDATA),
|
||||||
.RCLK (~RCLKN),
|
.RCLK (~RCLKN),
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
static void run_ice40_braminit(Module *module)
|
||||||
|
{
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
uint16_t mem[256];
|
||||||
|
|
||||||
|
/* Only consider cells we're interested in */
|
||||||
|
if (cell->type != "\\SB_RAM40_4K" &&
|
||||||
|
cell->type != "\\SB_RAM40_4KNR" &&
|
||||||
|
cell->type != "\\SB_RAM40_4KNW" &&
|
||||||
|
cell->type != "\\SB_RAM40_4KNRNW")
|
||||||
|
continue;
|
||||||
|
if (!cell->hasParam("\\INIT_FILE"))
|
||||||
|
continue;
|
||||||
|
std::string init_file = cell->getParam("\\INIT_FILE").decode_string();
|
||||||
|
cell->unsetParam("\\INIT_FILE");
|
||||||
|
if (init_file == "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Open file */
|
||||||
|
log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file.c_str());
|
||||||
|
|
||||||
|
std::ifstream f;
|
||||||
|
f.open(init_file.c_str());
|
||||||
|
if (f.fail()) {
|
||||||
|
log("Can not open file `%s`.\n", init_file.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Defaults to 0 */
|
||||||
|
memset(mem, 0x00, sizeof(mem));
|
||||||
|
|
||||||
|
/* Process each line */
|
||||||
|
bool in_comment = false;
|
||||||
|
int cursor = 0;
|
||||||
|
|
||||||
|
while (!f.eof())
|
||||||
|
{
|
||||||
|
std::string line, token;
|
||||||
|
std::getline(f, line);
|
||||||
|
|
||||||
|
for (int i = 0; i < GetSize(line); i++)
|
||||||
|
{
|
||||||
|
if (in_comment && line.substr(i, 2) == "*/") {
|
||||||
|
line[i] = ' ';
|
||||||
|
line[i+1] = ' ';
|
||||||
|
in_comment = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!in_comment && line.substr(i, 2) == "/*")
|
||||||
|
in_comment = true;
|
||||||
|
if (in_comment)
|
||||||
|
line[i] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
bool set_cursor = false;
|
||||||
|
long value;
|
||||||
|
|
||||||
|
token = next_token(line, " \t\r\n");
|
||||||
|
if (token.empty() || token.substr(0, 2) == "//")
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (token[0] == '@') {
|
||||||
|
token = token.substr(1);
|
||||||
|
set_cursor = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nptr = token.c_str();
|
||||||
|
char *endptr;
|
||||||
|
value = strtol(nptr, &endptr, 16);
|
||||||
|
if (!*nptr || *endptr) {
|
||||||
|
log("Can not parse %s `%s` for %s.\n",
|
||||||
|
set_cursor ? "address" : "value",
|
||||||
|
nptr, token.c_str()
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_cursor)
|
||||||
|
cursor = value;
|
||||||
|
else if (cursor >= 0 && cursor < 256)
|
||||||
|
mem[cursor++] = value;
|
||||||
|
else
|
||||||
|
log("Attempt to initialize non existent address %d\n", cursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set attributes */
|
||||||
|
const char *hex = "0123456789ABCDEF";
|
||||||
|
for (int i=0; i<16; i++) {
|
||||||
|
std::string val = "";
|
||||||
|
for (int j=15; j>=0; j--)
|
||||||
|
val += std::bitset<16>(mem[i*16+j]).to_string();
|
||||||
|
cell->setParam("\\INIT_" + std::string(1, hex[i]), RTLIL::Const::from_string(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Ice40BRAMInitPass : public Pass {
|
||||||
|
Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { }
|
||||||
|
void help() YS_OVERRIDE
|
||||||
|
{
|
||||||
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
|
log("\n");
|
||||||
|
log(" ice40_braminit\n");
|
||||||
|
log("\n");
|
||||||
|
log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n");
|
||||||
|
log("parameter and converts it into the required INIT_x attributes\n");
|
||||||
|
log("\n");
|
||||||
|
}
|
||||||
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
{
|
||||||
|
log_header(design, "Executing ICE40_BRAMINIT pass.\n");
|
||||||
|
|
||||||
|
size_t argidx;
|
||||||
|
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||||
|
// if (args[argidx] == "-???") {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
run_ice40_braminit(module);
|
||||||
|
}
|
||||||
|
} Ice40BRAMInitPass;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -257,6 +257,7 @@ struct SynthIce40Pass : public ScriptPass
|
||||||
{
|
{
|
||||||
run("memory_bram -rules +/ice40/brams.txt");
|
run("memory_bram -rules +/ice40/brams.txt");
|
||||||
run("techmap -map +/ice40/brams_map.v");
|
run("techmap -map +/ice40/brams_map.v");
|
||||||
|
run("ice40_braminit");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label("map"))
|
if (check_label("map"))
|
||||||
|
|
|
@ -32,7 +32,7 @@ module fa
|
||||||
wire VCC;
|
wire VCC;
|
||||||
|
|
||||||
assign VCC = 1'b1;
|
assign VCC = 1'b1;
|
||||||
|
|
||||||
cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x),
|
cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x),
|
||||||
.dataa(a_c),
|
.dataa(a_c),
|
||||||
.datab(b_c),
|
.datab(b_c),
|
||||||
|
@ -40,7 +40,7 @@ module fa
|
||||||
.datad(VCC));
|
.datad(VCC));
|
||||||
defparam syn__05_.lut_mask = 16'b1001011010010110;
|
defparam syn__05_.lut_mask = 16'b1001011010010110;
|
||||||
defparam syn__05_.sum_lutc_input = "datac";
|
defparam syn__05_.sum_lutc_input = "datac";
|
||||||
|
|
||||||
cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t),
|
cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t),
|
||||||
.dataa(cin_c),
|
.dataa(cin_c),
|
||||||
.datab(b_c),
|
.datab(b_c),
|
||||||
|
@ -48,11 +48,11 @@ module fa
|
||||||
.datad(VCC));
|
.datad(VCC));
|
||||||
defparam syn__06_.lut_mask = 16'b1110000011100000;
|
defparam syn__06_.lut_mask = 16'b1110000011100000;
|
||||||
defparam syn__06_.sum_lutc_input = "datac";
|
defparam syn__06_.sum_lutc_input = "datac";
|
||||||
|
|
||||||
endmodule // fa
|
endmodule // fa
|
||||||
|
|
||||||
module f_stage();
|
module f_stage();
|
||||||
|
|
||||||
endmodule // f_stage
|
endmodule // f_stage
|
||||||
|
|
||||||
module f_end();
|
module f_end();
|
||||||
|
@ -88,7 +88,7 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO);
|
||||||
.cin_c(C[0]),
|
.cin_c(C[0]),
|
||||||
.cout_t(C0[1]),
|
.cout_t(C0[1]),
|
||||||
.sum_x(Y[0]));
|
.sum_x(Y[0]));
|
||||||
|
|
||||||
genvar i;
|
genvar i;
|
||||||
generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice
|
generate for (i = 1; i < Y_WIDTH; i = i + 1) begin:slice
|
||||||
cycloneive_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i]));
|
cycloneive_lcell_comb #(.lut_mask(16'b0101_1010_0101_0000), .sum_lutc_input("cin")) arith_cell (.combout(Y[i]), .cout(CO[i]), .dataa(BB[i]), .datab(1'b1), .datac(1'b1), .datad(1'b1), .cin(C[i]));
|
||||||
|
|
|
@ -76,7 +76,7 @@ module \$lut (A, Y);
|
||||||
wire VCC;
|
wire VCC;
|
||||||
wire GND;
|
wire GND;
|
||||||
assign {VCC,GND} = {1'b1,1'b0};
|
assign {VCC,GND} = {1'b1,1'b0};
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (WIDTH == 1) begin
|
if (WIDTH == 1) begin
|
||||||
assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
|
assign Y = ~A[0]; // Not need to spend 1 logic cell for such an easy function
|
||||||
|
@ -151,7 +151,7 @@ module \$lut (A, Y);
|
||||||
TODO: There's not a just 7-input function on Cyclone V, see the following note:
|
TODO: There's not a just 7-input function on Cyclone V, see the following note:
|
||||||
**Extended LUT Mode**
|
**Extended LUT Mode**
|
||||||
Use extended LUT mode to implement a specific set of 7-input functions. The set must
|
Use extended LUT mode to implement a specific set of 7-input functions. The set must
|
||||||
be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
|
be a 2-to-1 multiplexer fed by two arbitrary 5-input functions sharing four inputs.
|
||||||
[source](Device Interfaces and Integration Basics for Cyclone V Devices).
|
[source](Device Interfaces and Integration Basics for Cyclone V Devices).
|
||||||
end*/
|
end*/
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,40 +1,54 @@
|
||||||
// module \$_DFF_N_ (input D, C, output Q); SB_DFFN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C)); endmodule
|
module \$_DFF_N_ (input D, C, output Q);
|
||||||
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
|
endmodule
|
||||||
|
|
||||||
module \$_DFF_P_ (input D, C, output Q);
|
module \$_DFF_P_ (input D, C, output Q);
|
||||||
SLE _TECHMAP_REPLACE_ (
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(1'b1), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
.D(D),
|
endmodule
|
||||||
.CLK(C),
|
|
||||||
.EN(1'b1),
|
module \$_DFF_NN0_ (input D, C, R, output Q);
|
||||||
.ALn(1'b1),
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
.ADn(1'b1),
|
endmodule
|
||||||
.SLn(1'b1),
|
|
||||||
.SD(1'b0),
|
module \$_DFF_NN1_ (input D, C, R, output Q);
|
||||||
.LAT(1'b0),
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
.Q(Q)
|
endmodule
|
||||||
);
|
|
||||||
|
module \$_DFF_NP0_ (input D, C, R, output Q);
|
||||||
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NP1_ (input D, C, R, output Q);
|
||||||
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(!C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_PN0_ (input D, C, R, output Q);
|
||||||
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_PN1_ (input D, C, R, output Q);
|
||||||
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_PP0_ (input D, C, R, output Q);
|
||||||
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b1), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module \$_DFF_PP1_ (input D, C, R, output Q);
|
||||||
|
SLE _TECHMAP_REPLACE_ (.D(D), .CLK(C), .EN(1'b1), .ALn(!R), .ADn(1'b0), .SLn(1'b1), .SD(1'b0), .LAT(1'b0), .Q(Q));
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
// module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
// module \$_DFFE_NN_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
||||||
// module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
// module \$_DFFE_PN_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(!E)); endmodule
|
||||||
//
|
//
|
||||||
// module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
// module \$_DFFE_NP_ (input D, C, E, output Q); SB_DFFNE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
||||||
// module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
// module \$_DFFE_PP_ (input D, C, E, output Q); SB_DFFE _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E)); endmodule
|
||||||
//
|
//
|
||||||
// module \$_DFF_NN0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
|
|
||||||
// module \$_DFF_NN1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
|
|
||||||
// module \$_DFF_PN0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(!R)); endmodule
|
|
||||||
// module \$_DFF_PN1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(!R)); endmodule
|
|
||||||
//
|
|
||||||
// module \$_DFF_NP0_ (input D, C, R, output Q); SB_DFFNR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
|
|
||||||
// module \$_DFF_NP1_ (input D, C, R, output Q); SB_DFFNS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
|
|
||||||
// module \$_DFF_PP0_ (input D, C, R, output Q); SB_DFFR _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(R)); endmodule
|
|
||||||
// module \$_DFF_PP1_ (input D, C, R, output Q); SB_DFFS _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .S(R)); endmodule
|
|
||||||
//
|
|
||||||
// module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
// module \$__DFFE_NN0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
||||||
// module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
// module \$__DFFE_NN1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
||||||
// module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
// module \$__DFFE_PN0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(!R)); endmodule
|
||||||
// module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
// module \$__DFFE_PN1 (input D, C, E, R, output Q); SB_DFFES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(!R)); endmodule
|
||||||
//
|
//
|
||||||
// module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
// module \$__DFFE_NP0 (input D, C, E, R, output Q); SB_DFFNER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
||||||
// module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
|
// module \$__DFFE_NP1 (input D, C, E, R, output Q); SB_DFFNES _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .S(R)); endmodule
|
||||||
// module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
// module \$__DFFE_PP0 (input D, C, E, R, output Q); SB_DFFER _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .E(E), .R(R)); endmodule
|
||||||
|
|
|
@ -1,39 +1,25 @@
|
||||||
module SLE (
|
// https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf
|
||||||
output Q,
|
|
||||||
input ADn,
|
module ADD2 (
|
||||||
input ALn,
|
|
||||||
input CLK,
|
input A, B,
|
||||||
input D,
|
output Y
|
||||||
input LAT,
|
|
||||||
input SD,
|
|
||||||
input EN,
|
|
||||||
input SLn
|
|
||||||
);
|
);
|
||||||
reg q_latch, q_ff;
|
assign Y = A & B;
|
||||||
|
endmodule
|
||||||
|
|
||||||
always @(posedge CLK, negedge ALn) begin
|
module ADD3 (
|
||||||
if (!ALn) begin
|
input A, B, C,
|
||||||
q_ff <= !ADn;
|
output Y
|
||||||
end else if (EN) begin
|
);
|
||||||
if (!SLn)
|
assign Y = A & B & C;
|
||||||
q_ff <= SD;
|
endmodule
|
||||||
else
|
|
||||||
q_ff <= D;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @* begin
|
module ADD4 (
|
||||||
if (!ALn) begin
|
input A, B, C, D,
|
||||||
q_latch <= !ADn;
|
output Y
|
||||||
end else if (CLK && EN) begin
|
);
|
||||||
if (!SLn)
|
assign Y = A & B & C & D;
|
||||||
q_ff <= SD;
|
|
||||||
else
|
|
||||||
q_ff <= D;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign Q = LAT ? q_latch : q_ff;
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module CFG1 (
|
module CFG1 (
|
||||||
|
@ -74,6 +60,238 @@ module CFG4 (
|
||||||
assign Y = INIT >> {D, C, B, A};
|
assign Y = INIT >> {D, C, B, A};
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
module BUFF (
|
||||||
|
input A,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module BUFD (
|
||||||
|
input A,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module CLKINT (
|
||||||
|
input A,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module CLKINT_PRESERVE (
|
||||||
|
input A,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module GCLKINT (
|
||||||
|
input A, EN,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A & EN;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module RCLKINT (
|
||||||
|
input A,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module RGCLKINT (
|
||||||
|
input A, EN,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A & EN;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module SLE (
|
||||||
|
output Q,
|
||||||
|
input ADn,
|
||||||
|
input ALn,
|
||||||
|
input CLK,
|
||||||
|
input D,
|
||||||
|
input LAT,
|
||||||
|
input SD,
|
||||||
|
input EN,
|
||||||
|
input SLn
|
||||||
|
);
|
||||||
|
reg q_latch, q_ff;
|
||||||
|
|
||||||
|
always @(posedge CLK, negedge ALn) begin
|
||||||
|
if (!ALn) begin
|
||||||
|
q_ff <= !ADn;
|
||||||
|
end else if (EN) begin
|
||||||
|
if (!SLn)
|
||||||
|
q_ff <= SD;
|
||||||
|
else
|
||||||
|
q_ff <= D;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @* begin
|
||||||
|
if (!ALn) begin
|
||||||
|
q_latch <= !ADn;
|
||||||
|
end else if (CLK && EN) begin
|
||||||
|
if (!SLn)
|
||||||
|
q_ff <= SD;
|
||||||
|
else
|
||||||
|
q_ff <= D;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign Q = LAT ? q_latch : q_ff;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// module AR1
|
||||||
|
// module FCEND_BUFF
|
||||||
|
// module FCINIT_BUFF
|
||||||
|
// module FLASH_FREEZE
|
||||||
|
// module OSCILLATOR
|
||||||
|
// module SYSRESET
|
||||||
|
// module SYSCTRL_RESET_STATUS
|
||||||
|
// module LIVE_PROBE_FB
|
||||||
|
// module GCLKBUF
|
||||||
|
// module GCLKBUF_DIFF
|
||||||
|
// module GCLKBIBUF
|
||||||
|
// module DFN1
|
||||||
|
// module DFN1C0
|
||||||
|
// module DFN1E1
|
||||||
|
// module DFN1E1C0
|
||||||
|
// module DFN1E1P0
|
||||||
|
// module DFN1P0
|
||||||
|
// module DLN1
|
||||||
|
// module DLN1C0
|
||||||
|
// module DLN1P0
|
||||||
|
|
||||||
|
module INV (
|
||||||
|
input A,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = !A;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module INVD (
|
||||||
|
input A,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = !A;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module MX2 (
|
||||||
|
input A, B, S,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = S ? B : A;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module MX4 (
|
||||||
|
input D0, D1, D2, D3, S0, S1,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = S1 ? (S0 ? D3 : D2) : (S0 ? D1 : D0);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module NAND2 (
|
||||||
|
input A, B,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = !(A & B);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module NAND3 (
|
||||||
|
input A, B, C,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = !(A & B & C);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module NAND4 (
|
||||||
|
input A, B, C, D,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = !(A & B & C & D);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module NOR2 (
|
||||||
|
input A, B,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = !(A | B);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module NOR3 (
|
||||||
|
input A, B, C,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = !(A | B | C);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module NOR4 (
|
||||||
|
input A, B, C, D,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = !(A | B | C | D);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module OR2 (
|
||||||
|
input A, B,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A | B;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module OR3 (
|
||||||
|
input A, B, C,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A | B | C;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module OR4 (
|
||||||
|
input A, B, C, D,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A | B | C | D;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module XOR2 (
|
||||||
|
input A, B,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A ^ B;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module XOR3 (
|
||||||
|
input A, B, C,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A ^ B ^ C;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module XOR4 (
|
||||||
|
input A, B, C, D,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A ^ B ^ C ^ D;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module XOR8 (
|
||||||
|
input A, B, C, D, E, F, G, H,
|
||||||
|
output Y
|
||||||
|
);
|
||||||
|
assign Y = A ^ B ^ C ^ D ^ E ^ F ^ G ^ H;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// module UJTAG
|
||||||
|
// module BIBUF
|
||||||
|
// module BIBUF_DIFF
|
||||||
|
// module CLKBIBUF
|
||||||
|
|
||||||
module CLKBUF (
|
module CLKBUF (
|
||||||
input PAD,
|
input PAD,
|
||||||
output Y
|
output Y
|
||||||
|
@ -81,6 +299,8 @@ module CLKBUF (
|
||||||
assign Y = PAD;
|
assign Y = PAD;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// module CLKBUF_DIFF
|
||||||
|
|
||||||
module INBUF (
|
module INBUF (
|
||||||
input PAD,
|
input PAD,
|
||||||
output Y
|
output Y
|
||||||
|
@ -88,9 +308,20 @@ module INBUF (
|
||||||
assign Y = PAD;
|
assign Y = PAD;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// module INBUF_DIFF
|
||||||
|
|
||||||
module OUTBUF (
|
module OUTBUF (
|
||||||
input D,
|
input D,
|
||||||
output PAD
|
output PAD
|
||||||
);
|
);
|
||||||
assign PAD = D;
|
assign PAD = D;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// module OUTBUF_DIFF
|
||||||
|
// module TRIBUFF
|
||||||
|
// module TRIBUFF_DIFF
|
||||||
|
// module DDR_IN
|
||||||
|
// module DDR_OUT
|
||||||
|
// module RAM1K18
|
||||||
|
// module RAM64x18
|
||||||
|
// module MACC
|
||||||
|
|
|
@ -23,6 +23,136 @@
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
static void handle_iobufs(Module *module, bool clkbuf_mode)
|
||||||
|
{
|
||||||
|
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 (clkbuf_mode && cell->type == "\\SLE") {
|
||||||
|
for (auto bit : sigmap(cell->getPort("\\CLK")))
|
||||||
|
clk_bits.insert(bit);
|
||||||
|
}
|
||||||
|
if (cell->type.in("\\INBUF", "\\OUTBUF", "\\TRIBUFF", "\\BIBUF", "\\CLKBUF", "\\CLKBIBUF",
|
||||||
|
"\\INBUF_DIFF", "\\OUTBUF_DIFF", "\\BIBUFF_DIFF", "\\TRIBUFF_DIFF", "\\CLKBUF_DIFF",
|
||||||
|
"\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF")) {
|
||||||
|
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 (clkbuf_mode && 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_clkint(Module *module)
|
||||||
|
{
|
||||||
|
SigMap sigmap(module);
|
||||||
|
|
||||||
|
pool<SigBit> clk_bits;
|
||||||
|
vector<SigBit> handled_clk_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("\\CLKBUF", "\\CLKBIBUF", "\\CLKBUF_DIFF", "\\GCLKBUF", "\\GCLKBUF_DIFF", "\\GCLKBIBUF",
|
||||||
|
"\\CLKINT", "\\CLKINT_PRESERVE", "\\GCLKINT", "\\RCLKINT", "\\RGCLKINT")) {
|
||||||
|
for (auto bit : sigmap(cell->getPort("\\Y")))
|
||||||
|
handled_clk_bits.push_back(bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto bit : handled_clk_bits)
|
||||||
|
clk_bits.erase(bit);
|
||||||
|
|
||||||
|
for (auto cell : vector<Cell*>(module->cells()))
|
||||||
|
for (auto &conn : cell->connections())
|
||||||
|
{
|
||||||
|
if (!cell->output(conn.first))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SigSpec sig = conn.second;
|
||||||
|
bool did_something = false;
|
||||||
|
|
||||||
|
for (auto &bit : sig) {
|
||||||
|
SigBit canonical_bit = sigmap(bit);
|
||||||
|
if (clk_bits.count(canonical_bit)) {
|
||||||
|
Cell *c = module->addCell(NEW_ID, "\\CLKINT");
|
||||||
|
SigBit new_bit = module->addWire(NEW_ID);
|
||||||
|
c->setPort("\\A", new_bit);
|
||||||
|
c->setPort("\\Y", bit);
|
||||||
|
log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit));
|
||||||
|
clk_bits.erase(canonical_bit);
|
||||||
|
did_something = true;
|
||||||
|
bit = new_bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (did_something)
|
||||||
|
cell->setPort(conn.first, sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto bit : clk_bits)
|
||||||
|
log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit));
|
||||||
|
}
|
||||||
|
|
||||||
struct Sf2IobsPass : public Pass {
|
struct Sf2IobsPass : public Pass {
|
||||||
Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
|
Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
|
||||||
void help() YS_OVERRIDE
|
void help() YS_OVERRIDE
|
||||||
|
@ -31,20 +161,25 @@ struct Sf2IobsPass : public Pass {
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" sf2_iobs [options] [selection]\n");
|
log(" sf2_iobs [options] [selection]\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("Add SF2 I/O buffers to top module IOs as needed.\n");
|
log("Add SF2 I/O buffers and global buffers to top module as needed.\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -clkbuf\n");
|
||||||
|
log(" Insert PAD->global_net clock buffers\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
{
|
{
|
||||||
|
bool clkbuf_mode = false;
|
||||||
|
|
||||||
log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
|
log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++)
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
{
|
{
|
||||||
// if (args[argidx] == "-singleton") {
|
if (args[argidx] == "-clkbuf") {
|
||||||
// singleton_mode = true;
|
clkbuf_mode = true;
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
@ -54,76 +189,8 @@ struct Sf2IobsPass : public Pass {
|
||||||
if (module == nullptr)
|
if (module == nullptr)
|
||||||
log_cmd_error("No top module found.\n");
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
SigMap sigmap(module);
|
handle_iobufs(module, clkbuf_mode);
|
||||||
|
handle_clkint(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;
|
} Sf2IobsPass;
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,9 @@ struct SynthSf2Pass : public ScriptPass
|
||||||
log(" -noiobs\n");
|
log(" -noiobs\n");
|
||||||
log(" run synthesis in \"block mode\", i.e. do not insert IO buffers\n");
|
log(" run synthesis in \"block mode\", i.e. do not insert IO buffers\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -clkbuf\n");
|
||||||
|
log(" insert direct PAD->global_net buffers\n");
|
||||||
|
log("\n");
|
||||||
log(" -retime\n");
|
log(" -retime\n");
|
||||||
log(" run 'abc' with -dff option\n");
|
log(" run 'abc' with -dff option\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -73,7 +76,7 @@ struct SynthSf2Pass : public ScriptPass
|
||||||
}
|
}
|
||||||
|
|
||||||
string top_opt, edif_file, vlog_file, json_file;
|
string top_opt, edif_file, vlog_file, json_file;
|
||||||
bool flatten, retime, iobs;
|
bool flatten, retime, iobs, clkbuf;
|
||||||
|
|
||||||
void clear_flags() YS_OVERRIDE
|
void clear_flags() YS_OVERRIDE
|
||||||
{
|
{
|
||||||
|
@ -84,6 +87,7 @@ struct SynthSf2Pass : public ScriptPass
|
||||||
flatten = true;
|
flatten = true;
|
||||||
retime = false;
|
retime = false;
|
||||||
iobs = true;
|
iobs = true;
|
||||||
|
clkbuf = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||||
|
@ -130,6 +134,10 @@ struct SynthSf2Pass : public ScriptPass
|
||||||
iobs = false;
|
iobs = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-clkbuf") {
|
||||||
|
clkbuf = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
@ -201,8 +209,10 @@ struct SynthSf2Pass : public ScriptPass
|
||||||
|
|
||||||
if (check_label("map_iobs"))
|
if (check_label("map_iobs"))
|
||||||
{
|
{
|
||||||
if (iobs || help_mode)
|
if (help_mode)
|
||||||
run("sf2_iobs", "(unless -noiobs)");
|
run("sf2_iobs [-clkbuf]", "(unless -noiobs)");
|
||||||
|
else if (iobs)
|
||||||
|
run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");
|
||||||
run("clean");
|
run("clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/brams_bb.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams.txt))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
|
||||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut2lut.v))
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
|
||||||
|
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
|
||||||
|
|
||||||
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
|
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
|
||||||
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
|
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// LCU
|
||||||
|
|
||||||
(* techmap_celltype = "$lcu" *)
|
(* techmap_celltype = "$lcu" *)
|
||||||
module _80_xilinx_lcu (P, G, CI, CO);
|
module _80_xilinx_lcu (P, G, CI, CO);
|
||||||
parameter WIDTH = 2;
|
parameter WIDTH = 2;
|
||||||
|
@ -28,10 +31,78 @@ module _80_xilinx_lcu (P, G, CI, CO);
|
||||||
|
|
||||||
wire _TECHMAP_FAIL_ = WIDTH <= 2;
|
wire _TECHMAP_FAIL_ = WIDTH <= 2;
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
|
||||||
|
`ifdef _CLB_CARRY
|
||||||
|
|
||||||
|
localparam CARRY4_COUNT = (WIDTH + 3) / 4;
|
||||||
|
localparam MAX_WIDTH = CARRY4_COUNT * 4;
|
||||||
|
localparam PAD_WIDTH = MAX_WIDTH - WIDTH;
|
||||||
|
|
||||||
|
wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, P & ~G};
|
||||||
|
wire [MAX_WIDTH-1:0] C = CO;
|
||||||
|
|
||||||
|
generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice
|
||||||
|
|
||||||
|
// Partially occupied CARRY4
|
||||||
|
if ((i+1)*4 > WIDTH) begin
|
||||||
|
|
||||||
|
// First one
|
||||||
|
if (i == 0) begin
|
||||||
|
CARRY4 carry4_1st_part
|
||||||
|
(
|
||||||
|
.CYINIT(CI),
|
||||||
|
.CI (1'd0),
|
||||||
|
.DI (G [(Y_WIDTH - 1):i*4]),
|
||||||
|
.S (S [(Y_WIDTH - 1):i*4]),
|
||||||
|
.CO (CO[(Y_WIDTH - 1):i*4]),
|
||||||
|
);
|
||||||
|
// Another one
|
||||||
|
end else begin
|
||||||
|
CARRY4 carry4_part
|
||||||
|
(
|
||||||
|
.CYINIT(1'd0),
|
||||||
|
.CI (C [i*4 - 1]),
|
||||||
|
.DI (G [(Y_WIDTH - 1):i*4]),
|
||||||
|
.S (S [(Y_WIDTH - 1):i*4]),
|
||||||
|
.CO (CO[(Y_WIDTH - 1):i*4]),
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
// Fully occupied CARRY4
|
||||||
|
end else begin
|
||||||
|
|
||||||
|
// First one
|
||||||
|
if (i == 0) begin
|
||||||
|
CARRY4 carry4_1st_full
|
||||||
|
(
|
||||||
|
.CYINIT(CI),
|
||||||
|
.CI (1'd0),
|
||||||
|
.DI (G [((i+1)*4 - 1):i*4]),
|
||||||
|
.S (S [((i+1)*4 - 1):i*4]),
|
||||||
|
.CO (CO[((i+1)*4 - 1):i*4]),
|
||||||
|
);
|
||||||
|
// Another one
|
||||||
|
end else begin
|
||||||
|
CARRY4 carry4_full
|
||||||
|
(
|
||||||
|
.CYINIT(1'd0),
|
||||||
|
.CI (C [i*4 - 1]),
|
||||||
|
.DI (G [((i+1)*4 - 1):i*4]),
|
||||||
|
.S (S [((i+1)*4 - 1):i*4]),
|
||||||
|
.CO (CO[((i+1)*4 - 1):i*4]),
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
`elsif _EXPLICIT_CARRY
|
||||||
|
|
||||||
wire [WIDTH-1:0] C = {CO, CI};
|
wire [WIDTH-1:0] C = {CO, CI};
|
||||||
wire [WIDTH-1:0] S = P & ~G;
|
wire [WIDTH-1:0] S = P & ~G;
|
||||||
|
|
||||||
genvar i;
|
|
||||||
generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
|
generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
|
||||||
MUXCY muxcy (
|
MUXCY muxcy (
|
||||||
.CI(C[i]),
|
.CI(C[i]),
|
||||||
|
@ -40,8 +111,28 @@ module _80_xilinx_lcu (P, G, CI, CO);
|
||||||
.O(CO[i])
|
.O(CO[i])
|
||||||
);
|
);
|
||||||
end endgenerate
|
end endgenerate
|
||||||
|
|
||||||
|
`else
|
||||||
|
|
||||||
|
wire [WIDTH-1:0] C = {CO, CI};
|
||||||
|
wire [WIDTH-1:0] S = P & ~G;
|
||||||
|
|
||||||
|
generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
|
||||||
|
MUXCY muxcy (
|
||||||
|
.CI(C[i]),
|
||||||
|
.DI(G[i]),
|
||||||
|
.S(S[i]),
|
||||||
|
.O(CO[i])
|
||||||
|
);
|
||||||
|
end endgenerate
|
||||||
|
`endif
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// ALU
|
||||||
|
|
||||||
(* techmap_celltype = "$alu" *)
|
(* techmap_celltype = "$alu" *)
|
||||||
module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
||||||
parameter A_SIGNED = 0;
|
parameter A_SIGNED = 0;
|
||||||
|
@ -49,6 +140,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
||||||
parameter A_WIDTH = 1;
|
parameter A_WIDTH = 1;
|
||||||
parameter B_WIDTH = 1;
|
parameter B_WIDTH = 1;
|
||||||
parameter Y_WIDTH = 1;
|
parameter Y_WIDTH = 1;
|
||||||
|
parameter _TECHMAP_CONSTVAL_CI_ = 0;
|
||||||
|
parameter _TECHMAP_CONSTMSK_CI_ = 0;
|
||||||
|
|
||||||
input [A_WIDTH-1:0] A;
|
input [A_WIDTH-1:0] A;
|
||||||
input [B_WIDTH-1:0] B;
|
input [B_WIDTH-1:0] B;
|
||||||
|
@ -66,16 +159,189 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
||||||
wire [Y_WIDTH-1:0] AA = A_buf;
|
wire [Y_WIDTH-1:0] AA = A_buf;
|
||||||
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
|
||||||
|
|
||||||
wire [Y_WIDTH-1:0] P = AA ^ BB;
|
genvar i;
|
||||||
wire [Y_WIDTH-1:0] G = AA & BB;
|
|
||||||
wire [Y_WIDTH-1:0] C = {CO, CI};
|
`ifdef _CLB_CARRY
|
||||||
wire [Y_WIDTH-1:0] S = P & ~G;
|
|
||||||
|
localparam CARRY4_COUNT = (Y_WIDTH + 3) / 4;
|
||||||
|
localparam MAX_WIDTH = CARRY4_COUNT * 4;
|
||||||
|
localparam PAD_WIDTH = MAX_WIDTH - Y_WIDTH;
|
||||||
|
|
||||||
|
wire [MAX_WIDTH-1:0] S = {{PAD_WIDTH{1'b0}}, AA ^ BB};
|
||||||
|
wire [MAX_WIDTH-1:0] DI = {{PAD_WIDTH{1'b0}}, AA & BB};
|
||||||
|
|
||||||
|
wire [MAX_WIDTH-1:0] C = CO;
|
||||||
|
|
||||||
genvar i;
|
genvar i;
|
||||||
|
generate for (i = 0; i < CARRY4_COUNT; i = i + 1) begin:slice
|
||||||
|
|
||||||
|
// Partially occupied CARRY4
|
||||||
|
if ((i+1)*4 > Y_WIDTH) begin
|
||||||
|
|
||||||
|
// First one
|
||||||
|
if (i == 0) begin
|
||||||
|
CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part
|
||||||
|
(
|
||||||
|
.CYINIT(CI),
|
||||||
|
.CI (1'd0),
|
||||||
|
.DI (DI[(Y_WIDTH - 1):i*4]),
|
||||||
|
.S (S [(Y_WIDTH - 1):i*4]),
|
||||||
|
.O (Y [(Y_WIDTH - 1):i*4]),
|
||||||
|
.CO (CO[(Y_WIDTH - 1):i*4])
|
||||||
|
);
|
||||||
|
// Another one
|
||||||
|
end else begin
|
||||||
|
CARRY4 carry4_part
|
||||||
|
(
|
||||||
|
.CYINIT(1'd0),
|
||||||
|
.CI (C [i*4 - 1]),
|
||||||
|
.DI (DI[(Y_WIDTH - 1):i*4]),
|
||||||
|
.S (S [(Y_WIDTH - 1):i*4]),
|
||||||
|
.O (Y [(Y_WIDTH - 1):i*4]),
|
||||||
|
.CO (CO[(Y_WIDTH - 1):i*4])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
// Fully occupied CARRY4
|
||||||
|
end else begin
|
||||||
|
|
||||||
|
// First one
|
||||||
|
if (i == 0) begin
|
||||||
|
CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full
|
||||||
|
(
|
||||||
|
.CYINIT(CI),
|
||||||
|
.CI (1'd0),
|
||||||
|
.DI (DI[((i+1)*4 - 1):i*4]),
|
||||||
|
.S (S [((i+1)*4 - 1):i*4]),
|
||||||
|
.O (Y [((i+1)*4 - 1):i*4]),
|
||||||
|
.CO (CO[((i+1)*4 - 1):i*4])
|
||||||
|
);
|
||||||
|
// Another one
|
||||||
|
end else begin
|
||||||
|
CARRY4 carry4_full
|
||||||
|
(
|
||||||
|
.CYINIT(1'd0),
|
||||||
|
.CI (C [i*4 - 1]),
|
||||||
|
.DI (DI[((i+1)*4 - 1):i*4]),
|
||||||
|
.S (S [((i+1)*4 - 1):i*4]),
|
||||||
|
.O (Y [((i+1)*4 - 1):i*4]),
|
||||||
|
.CO (CO[((i+1)*4 - 1):i*4])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
`elsif _EXPLICIT_CARRY
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] S = AA ^ BB;
|
||||||
|
wire [Y_WIDTH-1:0] DI = AA & BB;
|
||||||
|
|
||||||
|
wire CINIT;
|
||||||
|
// Carry chain.
|
||||||
|
//
|
||||||
|
// VPR requires that the carry chain never hit the fabric. The CO input
|
||||||
|
// to this techmap is the carry outputs for synthesis, e.g. might hit the
|
||||||
|
// fabric.
|
||||||
|
//
|
||||||
|
// So we maintain two wire sets, CO_CHAIN is the carry that is for VPR,
|
||||||
|
// e.g. off fabric dedicated chain. CO is the carry outputs that are
|
||||||
|
// available to the fabric.
|
||||||
|
wire [Y_WIDTH-1:0] CO_CHAIN;
|
||||||
|
wire [Y_WIDTH-1:0] C = {CO_CHAIN, CINIT};
|
||||||
|
|
||||||
|
// If carry chain is being initialized to a constant, techmap the constant
|
||||||
|
// source. Otherwise techmap the fabric source.
|
||||||
|
generate for (i = 0; i < 1; i = i + 1) begin:slice
|
||||||
|
CARRY0 #(.CYINIT_FABRIC(1)) carry(
|
||||||
|
.CI_INIT(CI),
|
||||||
|
.DI(DI[0]),
|
||||||
|
.S(S[0]),
|
||||||
|
.CO_CHAIN(CO_CHAIN[0]),
|
||||||
|
.CO_FABRIC(CO[0]),
|
||||||
|
.O(Y[0])
|
||||||
|
);
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
generate for (i = 1; i < Y_WIDTH-1; i = i + 1) begin:slice
|
||||||
|
if(i % 4 == 0) begin
|
||||||
|
CARRY0 carry (
|
||||||
|
.CI(C[i]),
|
||||||
|
.DI(DI[i]),
|
||||||
|
.S(S[i]),
|
||||||
|
.CO_CHAIN(CO_CHAIN[i]),
|
||||||
|
.CO_FABRIC(CO[i]),
|
||||||
|
.O(Y[i])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
CARRY carry (
|
||||||
|
.CI(C[i]),
|
||||||
|
.DI(DI[i]),
|
||||||
|
.S(S[i]),
|
||||||
|
.CO_CHAIN(CO_CHAIN[i]),
|
||||||
|
.CO_FABRIC(CO[i]),
|
||||||
|
.O(Y[i])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
generate for (i = Y_WIDTH-1; i < Y_WIDTH; i = i + 1) begin:slice
|
||||||
|
if(i % 4 == 0) begin
|
||||||
|
CARRY0 top_of_carry (
|
||||||
|
.CI(C[i]),
|
||||||
|
.DI(DI[i]),
|
||||||
|
.S(S[i]),
|
||||||
|
.CO_CHAIN(CO_CHAIN[i]),
|
||||||
|
.O(Y[i])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
CARRY top_of_carry (
|
||||||
|
.CI(C[i]),
|
||||||
|
.DI(DI[i]),
|
||||||
|
.S(S[i]),
|
||||||
|
.CO_CHAIN(CO_CHAIN[i]),
|
||||||
|
.O(Y[i])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
// Turns out CO_FABRIC and O both use [ABCD]MUX, so provide
|
||||||
|
// a non-congested path to output the top of the carry chain.
|
||||||
|
// Registering the output of the CARRY block would solve this, but not
|
||||||
|
// all designs do that.
|
||||||
|
if((i+1) % 4 == 0) begin
|
||||||
|
CARRY0 carry_output (
|
||||||
|
.CI(CO_CHAIN[i]),
|
||||||
|
.DI(0),
|
||||||
|
.S(0),
|
||||||
|
.O(CO[i])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
CARRY carry_output (
|
||||||
|
.CI(CO_CHAIN[i]),
|
||||||
|
.DI(0),
|
||||||
|
.S(0),
|
||||||
|
.O(CO[i])
|
||||||
|
);
|
||||||
|
end
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
`else
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] S = AA ^ BB;
|
||||||
|
wire [Y_WIDTH-1:0] DI = AA & BB;
|
||||||
|
|
||||||
|
wire [Y_WIDTH-1:0] C = {CO, CI};
|
||||||
|
|
||||||
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
|
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
|
||||||
MUXCY muxcy (
|
MUXCY muxcy (
|
||||||
.CI(C[i]),
|
.CI(C[i]),
|
||||||
.DI(G[i]),
|
.DI(DI[i]),
|
||||||
.S(S[i]),
|
.S(S[i]),
|
||||||
.O(CO[i])
|
.O(CO[i])
|
||||||
);
|
);
|
||||||
|
@ -86,6 +352,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
||||||
);
|
);
|
||||||
end endgenerate
|
end endgenerate
|
||||||
|
|
||||||
assign X = P;
|
`endif
|
||||||
|
|
||||||
|
assign X = S;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
|
@ -1,89 +1,21 @@
|
||||||
|
/*
|
||||||
module \$_DFF_N_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
|
*
|
||||||
|
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
|
||||||
module \$_DFFE_NP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
|
*
|
||||||
module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_R_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
module \$_DFF_NN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
|
* copyright notice and this permission notice appear in all copies.
|
||||||
module \$_DFF_NP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
|
*
|
||||||
module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_CLR_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(R)); endmodule
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
module \$_DFF_NN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
module \$_DFF_NP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|1), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0), .IS_C_INVERTED(|0), .IS_D_INVERTED(|0), .IS_PRE_INVERTED(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(R)); endmodule
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
`ifndef NO_LUT
|
*/
|
||||||
module \$lut (A, Y);
|
|
||||||
parameter WIDTH = 0;
|
|
||||||
parameter LUT = 0;
|
|
||||||
|
|
||||||
input [WIDTH-1:0] A;
|
|
||||||
output Y;
|
|
||||||
|
|
||||||
generate
|
|
||||||
if (WIDTH == 1) begin
|
|
||||||
LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
|
||||||
.I0(A[0]));
|
|
||||||
end else
|
|
||||||
if (WIDTH == 2) begin
|
|
||||||
LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
|
||||||
.I0(A[0]), .I1(A[1]));
|
|
||||||
end else
|
|
||||||
if (WIDTH == 3) begin
|
|
||||||
LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]));
|
|
||||||
end else
|
|
||||||
if (WIDTH == 4) begin
|
|
||||||
LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]));
|
|
||||||
end else
|
|
||||||
if (WIDTH == 5) begin
|
|
||||||
LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]), .I4(A[4]));
|
|
||||||
end else
|
|
||||||
if (WIDTH == 6) begin
|
|
||||||
LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
|
||||||
end else
|
|
||||||
if (WIDTH == 7) begin
|
|
||||||
wire T0, T1;
|
|
||||||
LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
|
||||||
LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
|
||||||
MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6]));
|
|
||||||
end else
|
|
||||||
if (WIDTH == 8) begin
|
|
||||||
wire T0, T1, T2, T3, T4, T5;
|
|
||||||
LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
|
||||||
LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
|
||||||
LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
|
||||||
LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3),
|
|
||||||
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
|
||||||
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
|
||||||
MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6]));
|
|
||||||
MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6]));
|
|
||||||
MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7]));
|
|
||||||
end else begin
|
|
||||||
wire _TECHMAP_FAIL_ = 1;
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
|
||||||
`endif
|
|
||||||
|
|
||||||
module \$__SHREG_ (input C, input D, input E, output Q);
|
module \$__SHREG_ (input C, input D, input E, output Q);
|
||||||
parameter DEPTH = 0;
|
parameter DEPTH = 0;
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
// See Xilinx UG953 and UG474 for a description of the cell types below.
|
// See Xilinx UG953 and UG474 for a description of the cell types below.
|
||||||
// http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf
|
// http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf
|
||||||
|
@ -104,6 +122,29 @@ module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
|
||||||
assign CO[3] = S[3] ? CO[2] : DI[3];
|
assign CO[3] = S[3] ? CO[2] : DI[3];
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
`ifdef _EXPLICIT_CARRY
|
||||||
|
|
||||||
|
module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S);
|
||||||
|
parameter CYINIT_FABRIC = 0;
|
||||||
|
wire CI_COMBINE;
|
||||||
|
if(CYINIT_FABRIC) begin
|
||||||
|
assign CI_COMBINE = CI_INIT;
|
||||||
|
end else begin
|
||||||
|
assign CI_COMBINE = CI;
|
||||||
|
end
|
||||||
|
assign CO_CHAIN = S ? CI_COMBINE : DI;
|
||||||
|
assign CO_FABRIC = S ? CI_COMBINE : DI;
|
||||||
|
assign O = S ^ CI_COMBINE;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S);
|
||||||
|
assign CO_CHAIN = S ? CI : DI;
|
||||||
|
assign CO_FABRIC = S ? CI : DI;
|
||||||
|
assign O = S ^ CI;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
||||||
module FDRE (output reg Q, input C, CE, D, R);
|
module FDRE (output reg Q, input C, CE, D, R);
|
||||||
parameter [0:0] INIT = 1'b0;
|
parameter [0:0] INIT = 1'b0;
|
||||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||||
|
@ -156,6 +197,30 @@ module FDPE (output reg Q, input C, CE, D, PRE);
|
||||||
endcase endgenerate
|
endcase endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
module FDRE_1 (output reg Q, input C, CE, D, R);
|
||||||
|
parameter [0:0] INIT = 1'b0;
|
||||||
|
initial Q <= INIT;
|
||||||
|
always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module FDSE_1 (output reg Q, input C, CE, D, S);
|
||||||
|
parameter [0:0] INIT = 1'b1;
|
||||||
|
initial Q <= INIT;
|
||||||
|
always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module FDCE_1 (output reg Q, input C, CE, D, CLR);
|
||||||
|
parameter [0:0] INIT = 1'b0;
|
||||||
|
initial Q <= INIT;
|
||||||
|
always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module FDPE_1 (output reg Q, input C, CE, D, PRE);
|
||||||
|
parameter [0:0] INIT = 1'b1;
|
||||||
|
initial Q <= INIT;
|
||||||
|
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
|
||||||
|
endmodule
|
||||||
|
|
||||||
module RAM64X1D (
|
module RAM64X1D (
|
||||||
output DPO, SPO,
|
output DPO, SPO,
|
||||||
input D, WCLK, WE,
|
input D, WCLK, WE,
|
||||||
|
|
|
@ -115,7 +115,7 @@ function xtract_cell_decl()
|
||||||
xtract_cell_decl PS7
|
xtract_cell_decl PS7
|
||||||
xtract_cell_decl PULLDOWN
|
xtract_cell_decl PULLDOWN
|
||||||
xtract_cell_decl PULLUP
|
xtract_cell_decl PULLUP
|
||||||
# xtract_cell_decl RAM128X1D
|
xtract_cell_decl RAM128X1D
|
||||||
xtract_cell_decl RAM128X1S
|
xtract_cell_decl RAM128X1S
|
||||||
xtract_cell_decl RAM256X1S
|
xtract_cell_decl RAM256X1S
|
||||||
xtract_cell_decl RAM32M
|
xtract_cell_decl RAM32M
|
||||||
|
@ -124,7 +124,7 @@ function xtract_cell_decl()
|
||||||
xtract_cell_decl RAM32X1S_1
|
xtract_cell_decl RAM32X1S_1
|
||||||
xtract_cell_decl RAM32X2S
|
xtract_cell_decl RAM32X2S
|
||||||
xtract_cell_decl RAM64M
|
xtract_cell_decl RAM64M
|
||||||
# xtract_cell_decl RAM64X1D
|
xtract_cell_decl RAM64X1D
|
||||||
xtract_cell_decl RAM64X1S
|
xtract_cell_decl RAM64X1S
|
||||||
xtract_cell_decl RAM64X1S_1
|
xtract_cell_decl RAM64X1S_1
|
||||||
xtract_cell_decl RAM64X2S
|
xtract_cell_decl RAM64X2S
|
||||||
|
|
|
@ -3695,6 +3695,25 @@ module RAM128X1S (...);
|
||||||
input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE;
|
input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
module RAM128X1D (
|
||||||
|
output DPO, SPO,
|
||||||
|
input D, WCLK, WE,
|
||||||
|
input [6:0] A, DPRA
|
||||||
|
);
|
||||||
|
parameter [127:0] INIT = 128'bx;
|
||||||
|
parameter IS_WCLK_INVERTED = 0;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module RAM64X1D (
|
||||||
|
output DPO, SPO,
|
||||||
|
input D, WCLK, WE,
|
||||||
|
input A0, A1, A2, A3, A4, A5,
|
||||||
|
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
|
||||||
|
);
|
||||||
|
parameter [63:0] INIT = 64'bx;
|
||||||
|
parameter IS_WCLK_INVERTED = 0;
|
||||||
|
endmodule
|
||||||
|
|
||||||
module RAM256X1S (...);
|
module RAM256X1S (...);
|
||||||
parameter [255:0] INIT = 256'h0;
|
parameter [255:0] INIT = 256'h0;
|
||||||
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// FF mapping
|
||||||
|
|
||||||
|
`ifndef _NO_FFS
|
||||||
|
|
||||||
|
module \$_DFF_N_ (input D, C, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
|
||||||
|
module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0)); endmodule
|
||||||
|
|
||||||
|
module \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
|
||||||
|
module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NN0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule
|
||||||
|
module \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule
|
||||||
|
module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule
|
||||||
|
module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule
|
||||||
|
|
||||||
|
module \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule
|
||||||
|
module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule
|
||||||
|
module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule
|
||||||
|
module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
module LUT1(output O, input I0);
|
|
||||||
parameter [1:0] INIT = 0;
|
|
||||||
\$lut #(
|
|
||||||
.WIDTH(1),
|
|
||||||
.LUT(INIT)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.A(I0),
|
|
||||||
.Y(O)
|
|
||||||
);
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module LUT2(output O, input I0, I1);
|
|
||||||
parameter [3:0] INIT = 0;
|
|
||||||
\$lut #(
|
|
||||||
.WIDTH(2),
|
|
||||||
.LUT(INIT)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.A({I1, I0}),
|
|
||||||
.Y(O)
|
|
||||||
);
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module LUT3(output O, input I0, I1, I2);
|
|
||||||
parameter [7:0] INIT = 0;
|
|
||||||
\$lut #(
|
|
||||||
.WIDTH(3),
|
|
||||||
.LUT(INIT)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.A({I2, I1, I0}),
|
|
||||||
.Y(O)
|
|
||||||
);
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module LUT4(output O, input I0, I1, I2, I3);
|
|
||||||
parameter [15:0] INIT = 0;
|
|
||||||
\$lut #(
|
|
||||||
.WIDTH(4),
|
|
||||||
.LUT(INIT)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.A({I3, I2, I1, I0}),
|
|
||||||
.Y(O)
|
|
||||||
);
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module LUT5(output O, input I0, I1, I2, I3, I4);
|
|
||||||
parameter [31:0] INIT = 0;
|
|
||||||
\$lut #(
|
|
||||||
.WIDTH(5),
|
|
||||||
.LUT(INIT)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.A({I4, I3, I2, I1, I0}),
|
|
||||||
.Y(O)
|
|
||||||
);
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module LUT6(output O, input I0, I1, I2, I3, I4, I5);
|
|
||||||
parameter [63:0] INIT = 0;
|
|
||||||
\$lut #(
|
|
||||||
.WIDTH(6),
|
|
||||||
.LUT(INIT)
|
|
||||||
) _TECHMAP_REPLACE_ (
|
|
||||||
.A({I5, I4, I3, I2, I1, I0}),
|
|
||||||
.Y(O)
|
|
||||||
);
|
|
||||||
endmodule
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// LUT mapping
|
||||||
|
|
||||||
|
`ifndef _NO_LUTS
|
||||||
|
|
||||||
|
module \$lut (A, Y);
|
||||||
|
parameter WIDTH = 0;
|
||||||
|
parameter LUT = 0;
|
||||||
|
|
||||||
|
input [WIDTH-1:0] A;
|
||||||
|
output Y;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (WIDTH == 1) begin
|
||||||
|
LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||||
|
.I0(A[0]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 2) begin
|
||||||
|
LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||||
|
.I0(A[0]), .I1(A[1]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 3) begin
|
||||||
|
LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 4) begin
|
||||||
|
LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 5) begin
|
||||||
|
LUT5 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]), .I4(A[4]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 6) begin
|
||||||
|
LUT6 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 7) begin
|
||||||
|
wire T0, T1;
|
||||||
|
LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
||||||
|
LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
||||||
|
MUXF7 fpga_mux_0 (.O(Y), .I0(T0), .I1(T1), .S(A[6]));
|
||||||
|
end else
|
||||||
|
if (WIDTH == 8) begin
|
||||||
|
wire T0, T1, T2, T3, T4, T5;
|
||||||
|
LUT6 #(.INIT(LUT[63:0])) fpga_lut_0 (.O(T0),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
||||||
|
LUT6 #(.INIT(LUT[127:64])) fpga_lut_1 (.O(T1),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
||||||
|
LUT6 #(.INIT(LUT[191:128])) fpga_lut_2 (.O(T2),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
||||||
|
LUT6 #(.INIT(LUT[255:192])) fpga_lut_3 (.O(T3),
|
||||||
|
.I0(A[0]), .I1(A[1]), .I2(A[2]),
|
||||||
|
.I3(A[3]), .I4(A[4]), .I5(A[5]));
|
||||||
|
MUXF7 fpga_mux_0 (.O(T4), .I0(T0), .I1(T1), .S(A[6]));
|
||||||
|
MUXF7 fpga_mux_1 (.O(T5), .I0(T2), .I1(T3), .S(A[6]));
|
||||||
|
MUXF8 fpga_mux_2 (.O(Y), .I0(T4), .I1(T5), .S(A[7]));
|
||||||
|
end else begin
|
||||||
|
wire _TECHMAP_FAIL_ = 1;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
|
@ -63,6 +63,12 @@ struct SynthXilinxPass : public Pass
|
||||||
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
|
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
|
||||||
log(" (this feature is experimental and incomplete)\n");
|
log(" (this feature is experimental and incomplete)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -nobram\n");
|
||||||
|
log(" disable infering of block rams\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -nodram\n");
|
||||||
|
log(" disable infering of distributed rams\n");
|
||||||
|
log("\n");
|
||||||
log(" -run <from_label>:<to_label>\n");
|
log(" -run <from_label>:<to_label>\n");
|
||||||
log(" only run the commands between the labels (see below). an empty\n");
|
log(" only run the commands between the labels (see below). an empty\n");
|
||||||
log(" from label is synonymous to 'begin', and empty to label is\n");
|
log(" from label is synonymous to 'begin', and empty to label is\n");
|
||||||
|
@ -90,11 +96,11 @@ struct SynthXilinxPass : public Pass
|
||||||
log(" coarse:\n");
|
log(" coarse:\n");
|
||||||
log(" synth -run coarse\n");
|
log(" synth -run coarse\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" bram:\n");
|
log(" bram: (only executed when '-nobram' is not given)\n");
|
||||||
log(" memory_bram -rules +/xilinx/brams.txt\n");
|
log(" memory_bram -rules +/xilinx/brams.txt\n");
|
||||||
log(" techmap -map +/xilinx/brams_map.v\n");
|
log(" techmap -map +/xilinx/brams_map.v\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" dram:\n");
|
log(" dram: (only executed when '-nodram' is not given)\n");
|
||||||
log(" memory_bram -rules +/xilinx/drams.txt\n");
|
log(" memory_bram -rules +/xilinx/drams.txt\n");
|
||||||
log(" techmap -map +/xilinx/drams_map.v\n");
|
log(" techmap -map +/xilinx/drams_map.v\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -106,15 +112,17 @@ struct SynthXilinxPass : public Pass
|
||||||
log(" opt -full\n");
|
log(" opt -full\n");
|
||||||
log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n");
|
log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n");
|
||||||
log(" shregmap -init_msb_first -params -enpol any_or_none\n");
|
log(" shregmap -init_msb_first -params -enpol any_or_none\n");
|
||||||
|
log(" techmap -map +/xilinx/ff_map.v\n");
|
||||||
log(" opt -fast\n");
|
log(" opt -fast\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" map_luts:\n");
|
log(" map_luts:\n");
|
||||||
log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n");
|
log(" abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!)\n");
|
||||||
|
log(" abc -lut 5 [-dff] (with '-vpr' only!)\n");
|
||||||
log(" clean\n");
|
log(" clean\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" map_cells:\n");
|
log(" map_cells:\n");
|
||||||
log(" techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n");
|
log(" techmap -map +/xilinx/cells_map.v\n");
|
||||||
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n");
|
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT\n");
|
||||||
log(" clean\n");
|
log(" clean\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" check:\n");
|
log(" check:\n");
|
||||||
|
@ -138,6 +146,8 @@ struct SynthXilinxPass : public Pass
|
||||||
bool flatten = false;
|
bool flatten = false;
|
||||||
bool retime = false;
|
bool retime = false;
|
||||||
bool vpr = false;
|
bool vpr = false;
|
||||||
|
bool nobram = false;
|
||||||
|
bool nodram = false;
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++)
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
@ -174,6 +184,14 @@ struct SynthXilinxPass : public Pass
|
||||||
vpr = true;
|
vpr = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-nobram") {
|
||||||
|
nobram = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-nodram") {
|
||||||
|
nodram = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
@ -188,9 +206,18 @@ struct SynthXilinxPass : public Pass
|
||||||
|
|
||||||
if (check_label(active, run_from, run_to, "begin"))
|
if (check_label(active, run_from, run_to, "begin"))
|
||||||
{
|
{
|
||||||
Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
|
if (vpr) {
|
||||||
|
Pass::call(design, "read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
|
||||||
|
} else {
|
||||||
|
Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
|
||||||
|
}
|
||||||
|
|
||||||
Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v");
|
Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v");
|
||||||
Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
|
|
||||||
|
if (!nobram) {
|
||||||
|
Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v");
|
||||||
|
}
|
||||||
|
|
||||||
Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
|
Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,14 +234,18 @@ struct SynthXilinxPass : public Pass
|
||||||
|
|
||||||
if (check_label(active, run_from, run_to, "bram"))
|
if (check_label(active, run_from, run_to, "bram"))
|
||||||
{
|
{
|
||||||
Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
|
if (!nobram) {
|
||||||
Pass::call(design, "techmap -map +/xilinx/brams_map.v");
|
Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
|
||||||
|
Pass::call(design, "techmap -map +/xilinx/brams_map.v");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label(active, run_from, run_to, "dram"))
|
if (check_label(active, run_from, run_to, "dram"))
|
||||||
{
|
{
|
||||||
Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
|
if (!nodram) {
|
||||||
Pass::call(design, "techmap -map +/xilinx/drams_map.v");
|
Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
|
||||||
|
Pass::call(design, "techmap -map +/xilinx/drams_map.v");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label(active, run_from, run_to, "fine"))
|
if (check_label(active, run_from, run_to, "fine"))
|
||||||
|
@ -224,8 +255,16 @@ struct SynthXilinxPass : public Pass
|
||||||
Pass::call(design, "dffsr2dff");
|
Pass::call(design, "dffsr2dff");
|
||||||
Pass::call(design, "dff2dffe");
|
Pass::call(design, "dff2dffe");
|
||||||
Pass::call(design, "opt -full");
|
Pass::call(design, "opt -full");
|
||||||
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v");
|
|
||||||
|
if (vpr) {
|
||||||
|
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
|
||||||
|
} else {
|
||||||
|
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v");
|
||||||
|
}
|
||||||
|
|
||||||
Pass::call(design, "shregmap -init_msb_first -params -enpol any_or_none");
|
Pass::call(design, "shregmap -init_msb_first -params -enpol any_or_none");
|
||||||
|
Pass::call(design, "techmap -map +/xilinx/ff_map.v");
|
||||||
|
Pass::call(design, "hierarchy -check");
|
||||||
Pass::call(design, "opt -fast");
|
Pass::call(design, "opt -fast");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,14 +272,13 @@ struct SynthXilinxPass : public Pass
|
||||||
{
|
{
|
||||||
Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
|
Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
|
||||||
Pass::call(design, "clean");
|
Pass::call(design, "clean");
|
||||||
|
Pass::call(design, "techmap -map +/xilinx/lut_map.v");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_label(active, run_from, run_to, "map_cells"))
|
if (check_label(active, run_from, run_to, "map_cells"))
|
||||||
{
|
{
|
||||||
Pass::call(design, "techmap -map +/xilinx/cells_map.v");
|
Pass::call(design, "techmap -map +/xilinx/cells_map.v");
|
||||||
if (vpr)
|
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT");
|
||||||
Pass::call(design, "techmap -map +/xilinx/lut2lut.v");
|
|
||||||
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT");
|
|
||||||
Pass::call(design, "clean");
|
Pass::call(design, "clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +292,7 @@ struct SynthXilinxPass : public Pass
|
||||||
if (check_label(active, run_from, run_to, "edif"))
|
if (check_label(active, run_from, run_to, "edif"))
|
||||||
{
|
{
|
||||||
if (!edif_file.empty())
|
if (!edif_file.empty())
|
||||||
Pass::call(design, stringf("write_edif %s", edif_file.c_str()));
|
Pass::call(design, stringf("write_edif -pvector bra %s", edif_file.c_str()));
|
||||||
}
|
}
|
||||||
if (check_label(active, run_from, run_to, "blif"))
|
if (check_label(active, run_from, run_to, "blif"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,6 @@ code_hdl_models_d_latch_gates.v combinational loop
|
||||||
code_hdl_models_dff_async_reset.v $adff
|
code_hdl_models_dff_async_reset.v $adff
|
||||||
code_hdl_models_tff_async_reset.v $adff
|
code_hdl_models_tff_async_reset.v $adff
|
||||||
code_hdl_models_uart.v $adff
|
code_hdl_models_uart.v $adff
|
||||||
code_specman_switch_fabric.v subfield assignment (bits() <= ...)
|
|
||||||
code_tidbits_asyn_reset.v $adff
|
code_tidbits_asyn_reset.v $adff
|
||||||
code_tidbits_reg_seq_example.v $adff
|
code_tidbits_reg_seq_example.v $adff
|
||||||
code_verilog_tutorial_always_example.v empty module
|
code_verilog_tutorial_always_example.v empty module
|
||||||
|
|
|
@ -120,3 +120,22 @@ module task_func_test04(input [7:0] in, output [7:0] out1, out2, out3, out4);
|
||||||
assign out3 = test3(in);
|
assign out3 = test3(in);
|
||||||
assign out4 = test4(in);
|
assign out4 = test4(in);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
// https://github.com/YosysHQ/yosys/issues/857
|
||||||
|
module task_func_test05(data_in,data_out,clk);
|
||||||
|
output reg data_out;
|
||||||
|
input data_in;
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
task myTask;
|
||||||
|
output out;
|
||||||
|
input in;
|
||||||
|
out = in;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
myTask(data_out,data_in);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures.
|
# This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures.
|
||||||
arraycells.v inst id[0] of
|
arraycells.v inst id[0] of
|
||||||
dff_different_styles.v
|
dff_different_styles.v
|
||||||
|
dff_init.v Initial value not supported
|
||||||
generate.v combinational loop
|
generate.v combinational loop
|
||||||
hierdefparam.v inst id[0] of
|
hierdefparam.v inst id[0] of
|
||||||
i2c_master_tests.v $adff
|
i2c_master_tests.v $adff
|
||||||
|
@ -12,7 +13,6 @@ multiplier.v inst id[0] of
|
||||||
muxtree.v drops modules
|
muxtree.v drops modules
|
||||||
omsp_dbg_uart.v $adff
|
omsp_dbg_uart.v $adff
|
||||||
operators.v $pow
|
operators.v $pow
|
||||||
paramods.v subfield assignment (bits() <= ...)
|
|
||||||
partsel.v drops modules
|
partsel.v drops modules
|
||||||
process.v drops modules
|
process.v drops modules
|
||||||
realexpr.v drops modules
|
realexpr.v drops modules
|
||||||
|
|
|
@ -8,7 +8,7 @@ verbose=false
|
||||||
keeprunning=false
|
keeprunning=false
|
||||||
makejmode=false
|
makejmode=false
|
||||||
frontend="verilog"
|
frontend="verilog"
|
||||||
backend_opts="-noattr -noexpr"
|
backend_opts="-noattr -noexpr -siminit"
|
||||||
autotb_opts=""
|
autotb_opts=""
|
||||||
include_opts=""
|
include_opts=""
|
||||||
xinclude_opts=""
|
xinclude_opts=""
|
||||||
|
@ -49,7 +49,7 @@ while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do
|
||||||
r)
|
r)
|
||||||
backend_opts="$backend_opts -norename" ;;
|
backend_opts="$backend_opts -norename" ;;
|
||||||
e)
|
e)
|
||||||
backend_opts="$( echo " $backend_opts " | sed 's, -noexpr ,,; s,^ ,,; s, $,,;'; )" ;;
|
backend_opts="$( echo " $backend_opts " | sed 's, -noexpr , ,; s,^ ,,; s, $,,;'; )" ;;
|
||||||
f)
|
f)
|
||||||
frontend="$OPTARG" ;;
|
frontend="$OPTARG" ;;
|
||||||
s)
|
s)
|
||||||
|
@ -175,7 +175,7 @@ do
|
||||||
if [ -n "$firrtl2verilog" ]; then
|
if [ -n "$firrtl2verilog" ]; then
|
||||||
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
|
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
|
||||||
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v
|
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v
|
||||||
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v -X verilog
|
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
|
||||||
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v
|
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in New Issue