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:
|
||||
- MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
|
||||
|
||||
# Latest clang on Mac OS X
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
env:
|
||||
- MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
|
||||
# # Latest clang on Mac OS X
|
||||
# - os: osx
|
||||
# osx_image: xcode9.4
|
||||
# env:
|
||||
# - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
|
||||
|
||||
before_install:
|
||||
- ./.travis/setup.sh
|
||||
|
|
5
Makefile
5
Makefile
|
@ -10,6 +10,7 @@ CONFIG := clang
|
|||
# features (the more the better)
|
||||
ENABLE_TCL := 1
|
||||
ENABLE_ABC := 1
|
||||
ENABLE_GLOB := 1
|
||||
ENABLE_PLUGINS := 1
|
||||
ENABLE_READLINE := 1
|
||||
ENABLE_EDITLINE := 0
|
||||
|
@ -298,6 +299,10 @@ LDLIBS += -ldl
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_GLOB),1)
|
||||
CXXFLAGS += -DYOSYS_ENABLE_GLOB
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_TCL),1)
|
||||
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
|
||||
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).
|
||||
|
||||
|
||||
Web Site
|
||||
========
|
||||
Web Site and Other Resources
|
||||
============================
|
||||
|
||||
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
|
||||
======
|
||||
|
@ -296,6 +309,9 @@ Verilog Attributes and non-standard features
|
|||
passes to identify input and output ports of cells. The Verilog backend
|
||||
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
|
||||
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.
|
||||
|
|
|
@ -130,7 +130,7 @@ struct EdifBackend : public Backend {
|
|||
bool port_rename = false;
|
||||
bool attr_properties = false;
|
||||
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
||||
bool nogndvcc = false, gndvccy = true;
|
||||
bool nogndvcc = false, gndvccy = false;
|
||||
CellTypes ct(design);
|
||||
EdifNames edif_names;
|
||||
|
||||
|
|
|
@ -165,11 +165,9 @@ struct FirrtlWorker
|
|||
|
||||
std::string fid(RTLIL::IdString internal_id)
|
||||
{
|
||||
const char *str = internal_id.c_str();
|
||||
return *str == '\\' ? str + 1 : str;
|
||||
return make_id(internal_id);
|
||||
}
|
||||
|
||||
|
||||
std::string cellname(RTLIL::Cell *cell)
|
||||
{
|
||||
return fid(cell->name).c_str();
|
||||
|
@ -219,29 +217,42 @@ struct FirrtlWorker
|
|||
if (it->second.size() > 0) {
|
||||
const SigSpec &secondSig = it->second;
|
||||
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.
|
||||
FDirection dir = getPortFDirection(it->first, instModule);
|
||||
std::string source, sink;
|
||||
std::string sourceExpr, sinkExpr;
|
||||
const SigSpec *sinkSig = nullptr;
|
||||
switch (dir) {
|
||||
case FD_INOUT:
|
||||
log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second));
|
||||
case FD_OUT:
|
||||
source = firstName;
|
||||
sink = secondName;
|
||||
sourceExpr = firstName;
|
||||
sinkExpr = secondExpr;
|
||||
sinkSig = &secondSig;
|
||||
break;
|
||||
case FD_NODIRECTION:
|
||||
log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second));
|
||||
/* FALL_THROUGH */
|
||||
case FD_IN:
|
||||
source = secondName;
|
||||
sink = firstName;
|
||||
sourceExpr = secondExpr;
|
||||
sinkExpr = firstName;
|
||||
break;
|
||||
default:
|
||||
log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir);
|
||||
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"));
|
||||
|
|
|
@ -48,7 +48,7 @@ struct ProtobufDesignSerializer
|
|||
|
||||
ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
|
||||
aig_mode_(aig_mode), use_selection_(use_selection) { }
|
||||
|
||||
|
||||
string get_name(IdString name)
|
||||
{
|
||||
return RTLIL::unescape_id(name);
|
||||
|
@ -60,7 +60,7 @@ struct ProtobufDesignSerializer
|
|||
{
|
||||
for (auto ¶m : parameters) {
|
||||
std::string key = get_name(param.first);
|
||||
|
||||
|
||||
|
||||
yosys::pb::Parameter pb_param;
|
||||
|
||||
|
@ -207,7 +207,7 @@ struct ProtobufDesignSerializer
|
|||
(*models)[aig.name] = pb_model;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void serialize_design(yosys::pb::Design *pb, Design *design)
|
||||
{
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
|
|
@ -416,6 +416,7 @@ struct Smt2Worker
|
|||
for (char ch : expr) {
|
||||
if (ch == 'A') processed_expr += get_bv(sig_a);
|
||||
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 == 'U') processed_expr += is_signed ? "s" : "u";
|
||||
else processed_expr += ch;
|
||||
|
@ -554,7 +555,7 @@ struct Smt2Worker
|
|||
|
||||
if (cell->type.in("$shift", "$shiftx")) {
|
||||
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)))",
|
||||
GetSize(cell->getPort("\\B")), 0), 's');
|
||||
} else {
|
||||
|
@ -887,8 +888,8 @@ struct Smt2Worker
|
|||
|
||||
string name_a = get_bool(cell->getPort("\\A"));
|
||||
string name_en = get_bool(cell->getPort("\\EN"));
|
||||
decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id,
|
||||
cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell)));
|
||||
string infostr = (cell->name[0] == '$' && cell->attributes.count("\\src")) ? cell->attributes.at("\\src").decode_string() : 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")
|
||||
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;
|
||||
|
||||
Const initword = init_data.extract(i*width, width, State::Sx);
|
||||
Const initmask = initword;
|
||||
bool gen_init_constr = false;
|
||||
|
||||
for (auto bit : initword.bits)
|
||||
if (bit == State::S0 || bit == State::S1)
|
||||
for (int k = 0; k < GetSize(initword); k++) {
|
||||
if (initword[k] == State::S0 || initword[k] == State::S1) {
|
||||
gen_init_constr = true;
|
||||
initmask[k] = State::S1;
|
||||
} else {
|
||||
initmask[k] = State::S0;
|
||||
initword[k] = State::S0;
|
||||
}
|
||||
}
|
||||
|
||||
if (gen_init_constr)
|
||||
{
|
||||
if (statebv)
|
||||
/* FIXME */;
|
||||
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(),
|
||||
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
|
||||
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;
|
||||
std::map<RTLIL::IdString, int> auto_name_map;
|
||||
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;
|
||||
dump_reg_init(ss, cell->getPort("\\Q"));
|
||||
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(" expressions.\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(" 32-bit constant values are by default dumped as decimal numbers,\n");
|
||||
log(" not bit pattern. This option deactivates this feature and instead\n");
|
||||
|
@ -1663,11 +1667,14 @@ struct VerilogBackend : public Backend {
|
|||
nostr = false;
|
||||
defparam = false;
|
||||
decimal = false;
|
||||
siminit = false;
|
||||
auto_prefix = "";
|
||||
|
||||
bool blackboxes = false;
|
||||
bool selected = false;
|
||||
|
||||
auto_name_map.clear();
|
||||
reg_wires.clear();
|
||||
reg_ct.clear();
|
||||
|
||||
reg_ct.insert("$dff");
|
||||
|
@ -1739,6 +1746,10 @@ struct VerilogBackend : public Backend {
|
|||
decimal = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-siminit") {
|
||||
siminit = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-blackboxes") {
|
||||
blackboxes = true;
|
||||
continue;
|
||||
|
@ -1770,6 +1781,8 @@ struct VerilogBackend : public Backend {
|
|||
dump_module(*f, "", it->second);
|
||||
}
|
||||
|
||||
auto_name_map.clear();
|
||||
reg_wires.clear();
|
||||
reg_ct.clear();
|
||||
}
|
||||
} 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.vm
|
||||
/example.stp
|
||||
/proj
|
||||
|
|
|
@ -1 +1,20 @@
|
|||
# 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
|
||||
create_clock -period 10.000 -waveform {0.000 5.000} [get_ports {clk}]
|
||||
|
|
|
@ -1,23 +1,64 @@
|
|||
module example (
|
||||
input clk,
|
||||
input EN,
|
||||
input SW1,
|
||||
input SW2,
|
||||
output LED1,
|
||||
output LED2,
|
||||
output LED3,
|
||||
output LED4,
|
||||
output LED5
|
||||
|
||||
output AA, AB, AC, AD,
|
||||
output AE, AF, AG, CA
|
||||
);
|
||||
|
||||
localparam BITS = 5;
|
||||
localparam BITS = 8;
|
||||
localparam LOG2DELAY = 22;
|
||||
|
||||
reg [BITS+LOG2DELAY-1:0] counter = 0;
|
||||
reg [BITS-1:0] outcnt;
|
||||
|
||||
always @(posedge clk) begin
|
||||
counter <= counter + EN;
|
||||
counter <= counter + SW1 + SW2 + 1;
|
||||
outcnt <= counter >> LOG2DELAY;
|
||||
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
|
||||
|
|
|
@ -8,13 +8,14 @@ new_project \
|
|||
-block_mode 0 \
|
||||
-hdl "VERILOG" \
|
||||
-family IGLOO2 \
|
||||
-die PA4MGL500 \
|
||||
-package tq144 \
|
||||
-die PA4MGL2500 \
|
||||
-package vf256 \
|
||||
-speed -1
|
||||
|
||||
import_files -hdl_source {netlist.vm}
|
||||
import_files -sdc {example.sdc}
|
||||
import_files -io_pdc {example.pdc}
|
||||
build_design_hierarchy
|
||||
set_option -synth 0
|
||||
|
||||
organize_tool_files -tool PLACEROUTE \
|
||||
|
@ -32,22 +33,25 @@ configure_tool -name PLACEROUTE \
|
|||
-params EFFORT_LEVEL:false \
|
||||
-params REPAIR_MIN_DELAY:false
|
||||
|
||||
puts ""
|
||||
puts "**> COMPILE"
|
||||
run_tool -name {COMPILE}
|
||||
puts "<** COMPILE"
|
||||
|
||||
puts ""
|
||||
puts "**> PLACEROUTE"
|
||||
run_tool -name {PLACEROUTE}
|
||||
puts "<** PLACEROUTE"
|
||||
|
||||
puts ""
|
||||
puts "**> VERIFYTIMING"
|
||||
run_tool -name {VERIFYTIMING}
|
||||
puts "<** VERIFYTIMING"
|
||||
|
||||
save_project
|
||||
|
||||
# puts "**> export_bitstream"
|
||||
# export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
|
||||
# puts "<** export_bitstream"
|
||||
puts ""
|
||||
puts "**> BITSTREAM"
|
||||
export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
|
||||
puts "<** BITSTREAM"
|
||||
|
||||
puts ""
|
||||
exit 0
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v
|
||||
LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v11.9/Libero/bin/libero SCRIPT:libero.tcl
|
||||
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_EQ2 = 0x00001000,
|
||||
MEM2REG_FL_CMPLX_LHS = 0x00002000,
|
||||
MEM2REG_FL_CONST_LHS = 0x00004000,
|
||||
MEM2REG_FL_VAR_LHS = 0x00008000,
|
||||
|
||||
/* proc flags */
|
||||
MEM2REG_FL_EQ1 = 0x01000000,
|
||||
|
@ -237,6 +239,7 @@ namespace AST
|
|||
bool has_const_only_constructs(bool &recommend_const_eval);
|
||||
void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
|
||||
AstNode *eval_const_function(AstNode *fcall);
|
||||
bool is_simple_const_expr();
|
||||
|
||||
// create a human-readable text representation of the AST (for debugging)
|
||||
void dumpAst(FILE *f, std::string indent) const;
|
||||
|
|
|
@ -544,7 +544,11 @@ struct AST_INTERNAL::ProcessGenerator
|
|||
break;
|
||||
|
||||
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;
|
||||
|
||||
case AST_PARAMETER:
|
||||
|
@ -1409,10 +1413,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
if (GetSize(en) != 1)
|
||||
en = current_module->ReduceBool(NEW_ID, en);
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << celltype << "$" << filename << ":" << linenum << "$" << (autoidx++);
|
||||
IdString cellname;
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
static int recursion_counter = 0;
|
||||
static pair<string, int> last_blocking_assignment_warn;
|
||||
static bool deep_recursion_warning = false;
|
||||
|
||||
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)
|
||||
{
|
||||
log_assert(type == AST_MODULE || type == AST_INTERFACE);
|
||||
last_blocking_assignment_warn = pair<string, int>();
|
||||
|
||||
deep_recursion_warning = true;
|
||||
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)
|
||||
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));
|
||||
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++) {
|
||||
AstNode *node = children[i];
|
||||
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) {
|
||||
AstNode *first_node = this_wire_scope[node->str];
|
||||
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 (flag_autowire) {
|
||||
if (flag_autowire || str == "\\$global_clock") {
|
||||
AstNode *auto_wire = new AstNode(AST_AUTOWIRE);
|
||||
auto_wire->str = str;
|
||||
current_ast_mod->children.push_back(auto_wire);
|
||||
|
@ -1499,6 +1509,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
newNode->children.push_back(assign_en);
|
||||
|
||||
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[0]->str = id_check;
|
||||
|
@ -1579,14 +1590,6 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
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";
|
||||
|
||||
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;
|
||||
bool mem_signed = children[0]->id2ast->is_signed;
|
||||
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);
|
||||
delete node_filename;
|
||||
delete node_memory;
|
||||
goto apply_newNode;
|
||||
}
|
||||
|
||||
|
@ -2210,6 +2215,8 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
std::map<std::string, std::string> replace_rules;
|
||||
vector<AstNode*> added_mod_children;
|
||||
dict<std::string, AstNode*> wire_cache;
|
||||
vector<AstNode*> new_stmts;
|
||||
vector<AstNode*> output_assignments;
|
||||
|
||||
if (current_block == NULL)
|
||||
{
|
||||
|
@ -2334,8 +2341,8 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
wire->port_id = 0;
|
||||
wire->is_input = false;
|
||||
wire->is_output = false;
|
||||
if (!child->is_output)
|
||||
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||
wire->is_reg = true;
|
||||
wire->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||
wire_cache[child->str] = 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, arg, wire_id);
|
||||
assign->children[0]->was_checked = true;
|
||||
|
||||
for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
|
||||
if (*it != current_block_child)
|
||||
continue;
|
||||
current_block->children.insert(it, assign);
|
||||
break;
|
||||
}
|
||||
if (child->is_input)
|
||||
new_stmts.push_back(assign);
|
||||
else
|
||||
output_assignments.push_back(assign);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2377,15 +2381,19 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
{
|
||||
AstNode *stmt = child->clone();
|
||||
stmt->replace_ids(prefix, replace_rules);
|
||||
|
||||
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.push_back(stmt);
|
||||
}
|
||||
|
||||
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:
|
||||
if (type == AST_FCALL) {
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -2936,6 +2944,16 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
|
|||
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
|
||||
if (flags & MEM2REG_FL_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)
|
||||
|
@ -2991,12 +3009,23 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
|
|||
log_assert((flags & ~0x000000ff) == 0);
|
||||
|
||||
for (auto child : children)
|
||||
if (ignore_children_counter > 0)
|
||||
ignore_children_counter--;
|
||||
else if (proc_flags_p)
|
||||
{
|
||||
if (lhs_children_counter > 0) {
|
||||
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);
|
||||
else
|
||||
child->mem2reg_as_needed_pass1(mem2reg_places, mem2reg_candidates, proc_flags, 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)
|
||||
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 (async_block == NULL) {
|
||||
|
@ -3277,6 +3339,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
|
|||
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()
|
||||
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
|
||||
|
||||
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:
|
||||
|
||||
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(" Generate automatic cover statements for all asserts\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(" Verbose log messages. (-vv is even more verbose than -v.)\n");
|
||||
log("\n");
|
||||
|
@ -2109,6 +2116,7 @@ struct VerificPass : public Pass {
|
|||
bool mode_autocover = false;
|
||||
bool flatten = false, extnets = false;
|
||||
string dumpfile;
|
||||
Map parameters(STRING_HASH);
|
||||
|
||||
for (argidx++; argidx < GetSize(args); argidx++) {
|
||||
if (args[argidx] == "-all") {
|
||||
|
@ -2147,6 +2155,15 @@ struct VerificPass : public Pass {
|
|||
mode_autocover = true;
|
||||
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") {
|
||||
mode_verific = true;
|
||||
continue;
|
||||
|
@ -2180,7 +2197,7 @@ struct VerificPass : public Pass {
|
|||
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_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;
|
||||
int i;
|
||||
|
||||
|
@ -2217,7 +2234,7 @@ struct VerificPass : public Pass {
|
|||
}
|
||||
|
||||
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;
|
||||
int i;
|
||||
|
||||
|
@ -2316,7 +2333,7 @@ struct ReadPass : public Pass {
|
|||
}
|
||||
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");
|
||||
|
||||
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(),
|
||||
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
|
||||
|
||||
|
|
|
@ -189,6 +189,14 @@ YOSYS_NAMESPACE_END
|
|||
"always_ff" { 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); }
|
||||
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
|
||||
"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_$\.]* {
|
||||
frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
|
||||
return TOK_ID;
|
||||
return TOK_ID;
|
||||
}
|
||||
|
||||
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
|
||||
|
|
|
@ -105,7 +105,8 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
|||
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 TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
|
||||
%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_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
|
||||
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
|
||||
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME
|
||||
%token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
|
||||
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
|
||||
%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
|
||||
%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> 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 <al> attr case_attr
|
||||
|
||||
|
@ -1329,6 +1329,14 @@ opt_label:
|
|||
$$ = NULL;
|
||||
};
|
||||
|
||||
opt_sva_label:
|
||||
TOK_SVA_LABEL ':' {
|
||||
$$ = $1;
|
||||
} |
|
||||
/* empty */ {
|
||||
$$ = NULL;
|
||||
};
|
||||
|
||||
opt_property:
|
||||
TOK_PROPERTY {
|
||||
$$ = true;
|
||||
|
@ -1337,9 +1345,6 @@ opt_property:
|
|||
$$ = false;
|
||||
};
|
||||
|
||||
opt_stmt_label:
|
||||
TOK_ID ':' | /* empty */;
|
||||
|
||||
modport_stmt:
|
||||
TOK_MODPORT TOK_ID {
|
||||
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;}
|
||||
|
||||
assert:
|
||||
opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {
|
||||
if (noassert_mode)
|
||||
opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' {
|
||||
if (noassert_mode) {
|
||||
delete $5;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
|
||||
} else {
|
||||
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 ')' ';' {
|
||||
if (noassume_mode)
|
||||
opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' {
|
||||
if (noassume_mode) {
|
||||
delete $5;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5));
|
||||
} else {
|
||||
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 ')' ';' {
|
||||
if (noassert_mode)
|
||||
opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
||||
if (noassert_mode) {
|
||||
delete $6;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
|
||||
} else {
|
||||
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 ')' ';' {
|
||||
if (noassume_mode)
|
||||
opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
||||
if (noassume_mode) {
|
||||
delete $6;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6));
|
||||
} else {
|
||||
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 ')' ';' {
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
|
||||
opt_sva_label TOK_COVER opt_property '(' expr ')' ';' {
|
||||
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 '(' ')' ';' {
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
|
||||
opt_sva_label TOK_COVER opt_property '(' ')' ';' {
|
||||
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 ';' {
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
|
||||
opt_sva_label TOK_COVER ';' {
|
||||
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 ')' ';' {
|
||||
if (norestrict_mode)
|
||||
opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' {
|
||||
if (norestrict_mode) {
|
||||
delete $5;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
|
||||
} else {
|
||||
AstNode *node = new AstNode(AST_ASSUME, $5);
|
||||
if ($1 != nullptr)
|
||||
node->str = *$1;
|
||||
ast_stack.back()->children.push_back(node);
|
||||
}
|
||||
if (!$3)
|
||||
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 ')' ';' {
|
||||
if (norestrict_mode)
|
||||
opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
|
||||
if (norestrict_mode) {
|
||||
delete $6;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
|
||||
} else {
|
||||
AstNode *node = new AstNode(AST_FAIR, $6);
|
||||
if ($1 != nullptr)
|
||||
node->str = *$1;
|
||||
ast_stack.back()->children.push_back(node);
|
||||
}
|
||||
if (!$3)
|
||||
log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
|
||||
if ($1 != nullptr)
|
||||
delete $1;
|
||||
};
|
||||
|
||||
assert_property:
|
||||
TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
|
||||
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4));
|
||||
opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
|
||||
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 ')' ';' {
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
|
||||
opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
|
||||
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 ')' ';' {
|
||||
ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5));
|
||||
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, $6));
|
||||
if ($1 != nullptr) {
|
||||
ast_stack.back()->children.back()->str = *$1;
|
||||
delete $1;
|
||||
}
|
||||
} |
|
||||
TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
|
||||
opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
|
||||
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 ')' ';' {
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4));
|
||||
opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
|
||||
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 ')' ';' {
|
||||
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)
|
||||
opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
|
||||
if (norestrict_mode) {
|
||||
delete $5;
|
||||
else
|
||||
ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
|
||||
} else {
|
||||
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:
|
||||
|
@ -1670,6 +1756,11 @@ case_expr_list:
|
|||
TOK_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 {
|
||||
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)
|
||||
for (auto &filename : log_hdump.at(header_id)) {
|
||||
log("Dumping current design to '%s'.\n", filename.c_str());
|
||||
if (yosys_xtrace)
|
||||
IdString::xtrace_db_dump();
|
||||
Pass::call(design, {"dump", "-o", filename});
|
||||
if (yosys_xtrace)
|
||||
log("#X# -- end of dump --\n");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
IdString::checkpoint();
|
||||
|
||||
int64_t time_ns = PerformanceTimer::query() - state.begin_ns;
|
||||
runtime_ns += time_ns;
|
||||
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_;
|
||||
dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_;
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -76,6 +76,9 @@ namespace RTLIL
|
|||
|
||||
struct IdString
|
||||
{
|
||||
#undef YOSYS_XTRACE_GET_PUT
|
||||
#undef YOSYS_SORT_ID_FREE_LIST
|
||||
|
||||
// the global id string cache
|
||||
|
||||
static struct destruct_guard_t {
|
||||
|
@ -89,9 +92,43 @@ namespace RTLIL
|
|||
static dict<char*, int, hash_cstr_ops> global_id_index_;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -107,6 +144,11 @@ namespace RTLIL
|
|||
auto it = global_id_index_.find((char*)p);
|
||||
if (it != global_id_index_.end()) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -124,16 +166,22 @@ namespace RTLIL
|
|||
global_refcount_storage_.at(idx)++;
|
||||
|
||||
// Avoid Create->Delete->Create pattern
|
||||
static IdString last_created_id;
|
||||
put_reference(last_created_id.index_);
|
||||
last_created_id.index_ = idx;
|
||||
get_reference(last_created_id.index_);
|
||||
if (last_created_idx_[last_created_idx_ptr_])
|
||||
put_reference(last_created_idx_[last_created_idx_ptr_]);
|
||||
last_created_idx_[last_created_idx_ptr_] = idx;
|
||||
get_reference(last_created_idx_[last_created_idx_ptr_]);
|
||||
last_created_idx_ptr_ = (last_created_idx_ptr_ + 1) & 7;
|
||||
|
||||
if (yosys_xtrace) {
|
||||
log("#X# New IdString '%s' with index %d.\n", p, idx);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -144,6 +192,12 @@ namespace RTLIL
|
|||
if (!destruct_guard.ok)
|
||||
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);
|
||||
|
||||
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);
|
||||
if (wire != nullptr && other.wire != nullptr)
|
||||
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 {
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
#elif defined(__APPLE__)
|
||||
|
@ -41,13 +41,15 @@
|
|||
# include <unistd.h>
|
||||
# include <dirent.h>
|
||||
# include <sys/stat.h>
|
||||
# include <glob.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <dirent.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && defined(YOSYS_ENABLE_GLOB)
|
||||
# include <glob.h>
|
||||
#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] == '"') {
|
||||
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)) {
|
||||
std::string token = text.substr(pos_begin, i-pos_begin+1);
|
||||
text = text.substr(i+1);
|
||||
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);
|
||||
|
@ -564,7 +572,7 @@ std::vector<std::string> glob_filename(const std::string &filename_pattern)
|
|||
{
|
||||
std::vector<std::string> results;
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || !defined(YOSYS_ENABLE_GLOB)
|
||||
results.push_back(filename_pattern);
|
||||
#else
|
||||
glob_t globbuf;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
//
|
||||
// yosys -- Yosys Open SYnthesis Suite
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2018 Serge Bazanski <q3k@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
|
||||
|
@ -73,7 +73,7 @@ message Module {
|
|||
BitVector bits = 2;
|
||||
}
|
||||
map<string, Port> port = 2;
|
||||
|
||||
|
||||
// Named cells in this module.
|
||||
message Cell {
|
||||
// Set to true when the name of this cell is automatically created and
|
||||
|
@ -129,7 +129,7 @@ message Model {
|
|||
TYPE_FALSE = 6;
|
||||
};
|
||||
Type type = 1;
|
||||
|
||||
|
||||
message Port {
|
||||
// Name of port.
|
||||
string portname = 1;
|
||||
|
@ -148,7 +148,7 @@ message Model {
|
|||
// Set for AND, NAND.
|
||||
Gate gate = 3;
|
||||
}
|
||||
|
||||
|
||||
// Set when the node drives given output port(s).
|
||||
message OutPort {
|
||||
// Name of port.
|
||||
|
|
|
@ -910,7 +910,7 @@ struct HierarchyPass : public Pass {
|
|||
if (m == nullptr)
|
||||
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);
|
||||
if (new_m_name.empty())
|
||||
continue;
|
||||
|
|
|
@ -53,6 +53,7 @@ struct WreduceWorker
|
|||
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
|
||||
std::set<SigBit> work_queue_bits;
|
||||
pool<SigBit> keep_bits;
|
||||
dict<SigBit, State> init_bits;
|
||||
|
||||
WreduceWorker(WreduceConfig *config, Module *module) :
|
||||
config(config), module(module), mi(module) { }
|
||||
|
@ -141,6 +142,7 @@ struct WreduceWorker
|
|||
|
||||
SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
|
||||
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
|
||||
Const initval;
|
||||
|
||||
int width_before = GetSize(sig_q);
|
||||
|
||||
|
@ -150,16 +152,24 @@ struct WreduceWorker
|
|||
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
|
||||
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--)
|
||||
{
|
||||
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);
|
||||
sig_d.remove(i);
|
||||
sig_q.remove(i);
|
||||
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]);
|
||||
sig_d.remove(i);
|
||||
sig_q.remove(i);
|
||||
|
@ -167,7 +177,7 @@ struct WreduceWorker
|
|||
}
|
||||
|
||||
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_q.remove(i);
|
||||
zero_ext = false;
|
||||
|
@ -183,10 +193,11 @@ struct WreduceWorker
|
|||
|
||||
if (GetSize(sig_q) == 0) {
|
||||
log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
|
||||
module->remove(cell);
|
||||
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));
|
||||
|
||||
for (auto bit : sig_d)
|
||||
|
@ -376,10 +387,18 @@ struct WreduceWorker
|
|||
|
||||
void run()
|
||||
{
|
||||
for (auto w : module->wires())
|
||||
for (auto w : module->wires()) {
|
||||
if (w->get_bool_attribute("\\keep"))
|
||||
for (auto bit : mi.sigmap(w))
|
||||
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())
|
||||
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
|
||||
.SECONDARY: passes/pmgen/ice40_dsp_pm.h
|
||||
|
||||
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/ice40_dsp.pmg passes/pmgen/pmgen.py
|
||||
$(P) cd passes/pmgen && python3 pmgen.py ice40_dsp
|
||||
passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
|
||||
$(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
|
||||
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:
|
||||
|
||||
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`
|
||||
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
|
||||
`select` lines.
|
||||
in `select` lines.
|
||||
|
||||
Index lines are using the `index <type> expr1 === expr2` syntax. `expr1` is
|
||||
evaluated during matcher initialization and the same restrictions apply as for
|
||||
|
|
|
@ -6,7 +6,11 @@ import pprint
|
|||
|
||||
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()
|
||||
udata_types = dict()
|
||||
|
@ -73,7 +77,7 @@ def rewrite_cpp(s):
|
|||
|
||||
return "".join(t)
|
||||
|
||||
with open("%s.pmg" % prefix, "r") as f:
|
||||
with open(pmgfile, "r") as f:
|
||||
while True:
|
||||
line = f.readline()
|
||||
if line == "": break
|
||||
|
@ -82,7 +86,7 @@ with open("%s.pmg" % prefix, "r") as f:
|
|||
cmd = line.split()
|
||||
if len(cmd) == 0 or cmd[0].startswith("//"): continue
|
||||
cmd = cmd[0]
|
||||
|
||||
|
||||
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)
|
||||
assert m
|
||||
|
@ -176,7 +180,7 @@ with open("%s.pmg" % prefix, "r") as f:
|
|||
|
||||
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("", file=f)
|
||||
|
||||
|
|
|
@ -8,4 +8,5 @@ OBJS += passes/sat/expose.o
|
|||
OBJS += passes/sat/assertpmux.o
|
||||
OBJS += passes/sat/clk2fflogic.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("the clock edge.\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");
|
||||
}
|
||||
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();
|
||||
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_d = cell->getPort("\\D");
|
||||
SigSpec sig_q = cell->getPort("\\Q");
|
||||
|
@ -120,6 +120,55 @@ struct Async2syncPass : public Pass {
|
|||
cell->type = "$dff";
|
||||
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())
|
||||
|
|
|
@ -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_PP1_", "$_DFF_P_");
|
||||
|
||||
log(" final dff cell mappings:\n");
|
||||
logmap_all();
|
||||
log(" final dff cell mappings:\n");
|
||||
logmap_all();
|
||||
|
||||
for (auto &it : design->modules_)
|
||||
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> inputs, pool<RTLIL::SigBit> outputs,
|
||||
std::function<GraphStyle(RTLIL::SigBit)> node_style =
|
||||
[](RTLIL::SigBit) { return GraphStyle{}; },
|
||||
[](RTLIL::SigBit) { return GraphStyle{}; },
|
||||
std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style =
|
||||
[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; },
|
||||
[](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; },
|
||||
string name = "")
|
||||
{
|
||||
FILE *f = fopen(filename.c_str(), "w");
|
||||
|
|
|
@ -30,7 +30,7 @@ endmodule
|
|||
module PADOUT (output padout, input padin, input oe);
|
||||
assign padout = padin;
|
||||
assign oe = oe;
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
module LUT4 (output dout,
|
||||
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);
|
||||
end
|
||||
assign dout = combout_rt & 1'b1;
|
||||
endmodule
|
||||
endmodule
|
||||
|
||||
module DFF (output q,
|
||||
input d, ck);
|
||||
reg q;
|
||||
always @(posedge ck)
|
||||
q <= d;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
|
|
@ -52,13 +52,13 @@ struct AnlogicEqnPass : public Pass {
|
|||
eqn += names[j];
|
||||
else
|
||||
eqn += std::string("~") + names[j];
|
||||
|
||||
|
||||
if (j!=(inputs-1)) eqn += "*";
|
||||
}
|
||||
eqn += ")+";
|
||||
}
|
||||
}
|
||||
if (eqn.empty()) return Const("0");
|
||||
if (eqn.empty()) return Const("0");
|
||||
eqn = eqn.substr(0, eqn.length()-1);
|
||||
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_sim.v))
|
||||
|
|
|
@ -33,7 +33,7 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO);
|
|||
input CI, BI;
|
||||
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;
|
||||
\$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;
|
||||
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 *)
|
||||
module IDDRX1F(
|
||||
input D, SCLK, RST,
|
||||
|
@ -164,6 +199,31 @@ module IDDRX1F(
|
|||
parameter GSR = "ENABLED";
|
||||
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 *)
|
||||
module ODDRX1F(
|
||||
input SCLK, RST, D0, D1,
|
||||
|
@ -172,6 +232,91 @@ module ODDRX1F(
|
|||
parameter GSR = "ENABLED";
|
||||
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 *)
|
||||
module CLKDIVF(
|
||||
input CLKI, RST, ALIGNWD,
|
||||
|
@ -181,6 +326,13 @@ module CLKDIVF(
|
|||
parameter DIV = "2.0";
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module ECLKSYNCB(
|
||||
input ECLKI, STOP,
|
||||
output ECLKO
|
||||
);
|
||||
endmodule
|
||||
|
||||
(* blackbox *)
|
||||
module DCCA(
|
||||
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_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
|
||||
module \$lut (A, Y);
|
||||
parameter WIDTH = 0;
|
||||
|
|
|
@ -57,7 +57,7 @@ module TRELLIS_RAM16X2 (
|
|||
input RAD0, RAD1, RAD2, RAD3,
|
||||
output DO0, DO1
|
||||
);
|
||||
parameter WCKMUX = "WCK";
|
||||
parameter WCKMUX = "WCK";
|
||||
parameter WREMUX = "WRE";
|
||||
parameter INITVAL_0 = 16'h0000;
|
||||
parameter INITVAL_1 = 16'h0000;
|
||||
|
@ -104,7 +104,7 @@ module TRELLIS_DPR16X4 (
|
|||
input [3:0] RAD,
|
||||
output [3:0] DO
|
||||
);
|
||||
parameter WCKMUX = "WCK";
|
||||
parameter WCKMUX = "WCK";
|
||||
parameter WREMUX = "WRE";
|
||||
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 [127:0] CEMUX = "1";
|
||||
parameter CLKMUX = "CLK";
|
||||
parameter LSRMUX = "LSR";
|
||||
parameter SRMODE = "LSR_OVER_CE";
|
||||
parameter REGSET = "RESET";
|
||||
parameter [127:0] LSRMODE = "LSR";
|
||||
|
||||
reg muxce;
|
||||
always @(*)
|
||||
|
@ -222,8 +223,13 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, output reg Q);
|
|||
|
||||
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
|
||||
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
|
||||
|
||||
localparam srval = (REGSET == "SET") ? 1'b1 : 1'b0;
|
||||
wire srval;
|
||||
generate
|
||||
if (LSRMODE == "PRLD")
|
||||
assign srval = M;
|
||||
else
|
||||
assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
|
||||
endgenerate
|
||||
|
||||
initial Q = srval;
|
||||
|
||||
|
@ -339,6 +345,8 @@ module TRELLIS_SLICE(
|
|||
parameter REG1_SD = "0";
|
||||
parameter REG0_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_1 = "NO";
|
||||
parameter WREMUX = "WRE";
|
||||
|
@ -428,10 +436,11 @@ module TRELLIS_SLICE(
|
|||
.CLKMUX(CLKMUX),
|
||||
.LSRMUX(LSRMUX),
|
||||
.SRMODE(SRMODE),
|
||||
.REGSET(REG0_REGSET)
|
||||
.REGSET(REG0_REGSET),
|
||||
.LSRMODE(REG0_LSRMODE)
|
||||
) ff_0 (
|
||||
.CLK(CLK), .LSR(LSR), .CE(CE),
|
||||
.DI(muxdi0),
|
||||
.DI(muxdi0), .M(M0),
|
||||
.Q(Q0)
|
||||
);
|
||||
TRELLIS_FF #(
|
||||
|
@ -440,10 +449,11 @@ module TRELLIS_SLICE(
|
|||
.CLKMUX(CLKMUX),
|
||||
.LSRMUX(LSRMUX),
|
||||
.SRMODE(SRMODE),
|
||||
.REGSET(REG1_REGSET)
|
||||
.REGSET(REG1_REGSET),
|
||||
.LSRMODE(REG1_LSRMODE)
|
||||
) ff_1 (
|
||||
.CLK(CLK), .LSR(LSR), .CE(CE),
|
||||
.DI(muxdi1),
|
||||
.DI(muxdi1), .M(M1),
|
||||
.Q(Q1)
|
||||
);
|
||||
endmodule
|
||||
|
@ -547,3 +557,20 @@ module DP16KD(
|
|||
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
|
||||
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("opt_expr -mux_undef");
|
||||
run("simplemap");
|
||||
// TODO
|
||||
#if 0
|
||||
run("ecp5_ffinit");
|
||||
#endif
|
||||
}
|
||||
|
||||
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 B_WIDTH = 1;
|
||||
parameter Y_WIDTH = 1;
|
||||
|
||||
|
||||
input [A_WIDTH-1:0] A;
|
||||
input [B_WIDTH-1:0] B;
|
||||
output [Y_WIDTH-1:0] X, Y;
|
||||
|
||||
|
||||
input CI, BI;
|
||||
output [Y_WIDTH-1:0] CO;
|
||||
|
||||
|
||||
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
|
||||
|
||||
|
||||
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(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] BB = BI ? ~B_buf : B_buf;
|
||||
wire [Y_WIDTH-1:0] C = {CO, CI};
|
||||
|
||||
|
||||
genvar i;
|
||||
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
|
||||
ALU #(.ALU_MODE(32'b0))
|
||||
|
|
|
@ -111,7 +111,7 @@ struct SynthGowinPass : public ScriptPass
|
|||
if (args[argidx] == "-noflatten") {
|
||||
flatten = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
|
|
@ -112,14 +112,14 @@ module GP_OBUFT(input IN, input OE, output OUT);
|
|||
endmodule
|
||||
|
||||
module \$lut (A, Y);
|
||||
parameter WIDTH = 0;
|
||||
parameter LUT = 0;
|
||||
parameter WIDTH = 0;
|
||||
parameter LUT = 0;
|
||||
|
||||
input [WIDTH-1:0] A;
|
||||
output Y;
|
||||
input [WIDTH-1:0] A;
|
||||
output Y;
|
||||
|
||||
generate
|
||||
if (WIDTH == 1) begin
|
||||
generate
|
||||
if (WIDTH == 1) begin
|
||||
if(LUT == 2'b01) begin
|
||||
GP_INV _TECHMAP_REPLACE_ (.OUT(Y), .IN(A[0]) );
|
||||
end
|
||||
|
@ -127,22 +127,22 @@ module \$lut (A, Y);
|
|||
GP_2LUT #(.INIT({2'b00, LUT})) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||
.IN0(A[0]), .IN1(1'b0));
|
||||
end
|
||||
end else
|
||||
if (WIDTH == 2) begin
|
||||
GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||
.IN0(A[0]), .IN1(A[1]));
|
||||
end else
|
||||
if (WIDTH == 3) begin
|
||||
GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]));
|
||||
end else
|
||||
if (WIDTH == 4) begin
|
||||
GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3]));
|
||||
end else begin
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
end
|
||||
endgenerate
|
||||
end else
|
||||
if (WIDTH == 2) begin
|
||||
GP_2LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||
.IN0(A[0]), .IN1(A[1]));
|
||||
end else
|
||||
if (WIDTH == 3) begin
|
||||
GP_3LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]));
|
||||
end else
|
||||
if (WIDTH == 4) begin
|
||||
GP_4LUT #(.INIT(LUT)) _TECHMAP_REPLACE_ (.OUT(Y),
|
||||
.IN0(A[0]), .IN1(A[1]), .IN2(A[2]), .IN3(A[3]));
|
||||
end else begin
|
||||
wire _TECHMAP_FAIL_ = 1;
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
||||
module \$__COUNT_ (CE, CLK, OUT, POUT, RST, UP);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
OBJS += techlibs/ice40/synth_ice40.o
|
||||
OBJS += techlibs/ice40/ice40_braminit.o
|
||||
OBJS += techlibs/ice40/ice40_ffssr.o
|
||||
OBJS += techlibs/ice40/ice40_ffinit.o
|
||||
OBJS += techlibs/ice40/ice40_opt.o
|
||||
|
|
|
@ -7,8 +7,8 @@ module \$__ICE40_RAM4K (
|
|||
input [10:0] WADDR,
|
||||
input [15:0] MASK, WDATA
|
||||
);
|
||||
parameter integer READ_MODE = 0;
|
||||
parameter integer WRITE_MODE = 0;
|
||||
parameter [1:0] READ_MODE = 0;
|
||||
parameter [1:0] WRITE_MODE = 0;
|
||||
parameter [0:0] NEGCLK_R = 0;
|
||||
parameter [0:0] NEGCLK_W = 0;
|
||||
|
||||
|
|
|
@ -326,6 +326,8 @@ module SB_RAM40_4K (
|
|||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
parameter INIT_FILE = "";
|
||||
|
||||
`ifndef BLACKBOX
|
||||
wire [15:0] WMASK_I;
|
||||
wire [15:0] RMASK_I;
|
||||
|
@ -408,43 +410,27 @@ module SB_RAM40_4K (
|
|||
reg [15:0] memory [0:255];
|
||||
|
||||
initial begin
|
||||
for (i=0; i<16; i=i+1) begin
|
||||
`ifdef YOSYS
|
||||
memory[ 0*16 + i] <= INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] <= INIT_1[16*i +: 16];
|
||||
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];
|
||||
`else
|
||||
memory[ 0*16 + i] = INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] = INIT_1[16*i +: 16];
|
||||
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
|
||||
if (INIT_FILE != "")
|
||||
$readmemh(INIT_FILE, memory);
|
||||
else
|
||||
for (i=0; i<16; i=i+1) begin
|
||||
memory[ 0*16 + i] = INIT_0[16*i +: 16];
|
||||
memory[ 1*16 + i] = INIT_1[16*i +: 16];
|
||||
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];
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge WCLK) begin
|
||||
|
@ -504,6 +490,8 @@ module SB_RAM40_4KNR (
|
|||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
parameter INIT_FILE = "";
|
||||
|
||||
SB_RAM40_4K #(
|
||||
.WRITE_MODE(WRITE_MODE),
|
||||
.READ_MODE (READ_MODE ),
|
||||
|
@ -522,7 +510,8 @@ module SB_RAM40_4KNR (
|
|||
.INIT_C (INIT_C ),
|
||||
.INIT_D (INIT_D ),
|
||||
.INIT_E (INIT_E ),
|
||||
.INIT_F (INIT_F )
|
||||
.INIT_F (INIT_F ),
|
||||
.INIT_FILE (INIT_FILE )
|
||||
) RAM (
|
||||
.RDATA(RDATA),
|
||||
.RCLK (~RCLKN),
|
||||
|
@ -566,6 +555,8 @@ module SB_RAM40_4KNW (
|
|||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
parameter INIT_FILE = "";
|
||||
|
||||
SB_RAM40_4K #(
|
||||
.WRITE_MODE(WRITE_MODE),
|
||||
.READ_MODE (READ_MODE ),
|
||||
|
@ -584,7 +575,8 @@ module SB_RAM40_4KNW (
|
|||
.INIT_C (INIT_C ),
|
||||
.INIT_D (INIT_D ),
|
||||
.INIT_E (INIT_E ),
|
||||
.INIT_F (INIT_F )
|
||||
.INIT_F (INIT_F ),
|
||||
.INIT_FILE (INIT_FILE )
|
||||
) RAM (
|
||||
.RDATA(RDATA),
|
||||
.RCLK (RCLK ),
|
||||
|
@ -628,6 +620,8 @@ module SB_RAM40_4KNRNW (
|
|||
parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
|
||||
|
||||
parameter INIT_FILE = "";
|
||||
|
||||
SB_RAM40_4K #(
|
||||
.WRITE_MODE(WRITE_MODE),
|
||||
.READ_MODE (READ_MODE ),
|
||||
|
@ -646,7 +640,8 @@ module SB_RAM40_4KNRNW (
|
|||
.INIT_C (INIT_C ),
|
||||
.INIT_D (INIT_D ),
|
||||
.INIT_E (INIT_E ),
|
||||
.INIT_F (INIT_F )
|
||||
.INIT_F (INIT_F ),
|
||||
.INIT_FILE (INIT_FILE )
|
||||
) RAM (
|
||||
.RDATA(RDATA),
|
||||
.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("techmap -map +/ice40/brams_map.v");
|
||||
run("ice40_braminit");
|
||||
}
|
||||
|
||||
if (check_label("map"))
|
||||
|
|
|
@ -32,7 +32,7 @@ module fa
|
|||
wire VCC;
|
||||
|
||||
assign VCC = 1'b1;
|
||||
|
||||
|
||||
cycloneiv_lcell_comb gen_sum_0 (.combout(sum_x),
|
||||
.dataa(a_c),
|
||||
.datab(b_c),
|
||||
|
@ -40,7 +40,7 @@ module fa
|
|||
.datad(VCC));
|
||||
defparam syn__05_.lut_mask = 16'b1001011010010110;
|
||||
defparam syn__05_.sum_lutc_input = "datac";
|
||||
|
||||
|
||||
cycloneiv_lcell_comb gen_cout_0 (.combout(cout_t),
|
||||
.dataa(cin_c),
|
||||
.datab(b_c),
|
||||
|
@ -48,11 +48,11 @@ module fa
|
|||
.datad(VCC));
|
||||
defparam syn__06_.lut_mask = 16'b1110000011100000;
|
||||
defparam syn__06_.sum_lutc_input = "datac";
|
||||
|
||||
|
||||
endmodule // fa
|
||||
|
||||
module f_stage();
|
||||
|
||||
|
||||
endmodule // f_stage
|
||||
|
||||
module f_end();
|
||||
|
@ -88,7 +88,7 @@ module _80_cycloneive_alu (A, B, CI, BI, X, Y, CO);
|
|||
.cin_c(C[0]),
|
||||
.cout_t(C0[1]),
|
||||
.sum_x(Y[0]));
|
||||
|
||||
|
||||
genvar i;
|
||||
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]));
|
||||
|
|
|
@ -76,7 +76,7 @@ module \$lut (A, Y);
|
|||
wire VCC;
|
||||
wire GND;
|
||||
assign {VCC,GND} = {1'b1,1'b0};
|
||||
|
||||
|
||||
generate
|
||||
if (WIDTH == 1) begin
|
||||
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:
|
||||
**Extended LUT Mode**
|
||||
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).
|
||||
end*/
|
||||
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);
|
||||
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)
|
||||
);
|
||||
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_NN0_ (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_NN1_ (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_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
|
||||
|
||||
// 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_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 \$_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_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_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_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
|
||||
|
|
|
@ -1,39 +1,25 @@
|
|||
module SLE (
|
||||
output Q,
|
||||
input ADn,
|
||||
input ALn,
|
||||
input CLK,
|
||||
input D,
|
||||
input LAT,
|
||||
input SD,
|
||||
input EN,
|
||||
input SLn
|
||||
// https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf
|
||||
|
||||
module ADD2 (
|
||||
|
||||
input A, B,
|
||||
output Y
|
||||
);
|
||||
reg q_latch, q_ff;
|
||||
assign Y = A & B;
|
||||
endmodule
|
||||
|
||||
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
|
||||
module ADD3 (
|
||||
input A, B, C,
|
||||
output Y
|
||||
);
|
||||
assign Y = A & B & C;
|
||||
endmodule
|
||||
|
||||
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;
|
||||
module ADD4 (
|
||||
input A, B, C, D,
|
||||
output Y
|
||||
);
|
||||
assign Y = A & B & C & D;
|
||||
endmodule
|
||||
|
||||
module CFG1 (
|
||||
|
@ -74,6 +60,238 @@ module CFG4 (
|
|||
assign Y = INIT >> {D, C, B, A};
|
||||
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 (
|
||||
input PAD,
|
||||
output Y
|
||||
|
@ -81,6 +299,8 @@ module CLKBUF (
|
|||
assign Y = PAD;
|
||||
endmodule
|
||||
|
||||
// module CLKBUF_DIFF
|
||||
|
||||
module INBUF (
|
||||
input PAD,
|
||||
output Y
|
||||
|
@ -88,9 +308,20 @@ module INBUF (
|
|||
assign Y = PAD;
|
||||
endmodule
|
||||
|
||||
// module INBUF_DIFF
|
||||
|
||||
module OUTBUF (
|
||||
input D,
|
||||
output PAD
|
||||
);
|
||||
assign PAD = D;
|
||||
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
|
||||
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 {
|
||||
Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
|
||||
void help() YS_OVERRIDE
|
||||
|
@ -31,20 +161,25 @@ struct Sf2IobsPass : public Pass {
|
|||
log("\n");
|
||||
log(" sf2_iobs [options] [selection]\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");
|
||||
}
|
||||
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");
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
// if (args[argidx] == "-singleton") {
|
||||
// singleton_mode = true;
|
||||
// continue;
|
||||
// }
|
||||
if (args[argidx] == "-clkbuf") {
|
||||
clkbuf_mode = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -54,76 +189,8 @@ struct Sf2IobsPass : public Pass {
|
|||
if (module == nullptr)
|
||||
log_cmd_error("No top module found.\n");
|
||||
|
||||
SigMap sigmap(module);
|
||||
|
||||
pool<SigBit> clk_bits;
|
||||
pool<SigBit> handled_io_bits;
|
||||
dict<SigBit, SigBit> rewrite_bits;
|
||||
vector<pair<Cell*, SigBit>> pad_bits;
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type == "\\SLE") {
|
||||
for (auto bit : sigmap(cell->getPort("\\CLK")))
|
||||
clk_bits.insert(bit);
|
||||
}
|
||||
if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) {
|
||||
for (auto bit : sigmap(cell->getPort("\\PAD")))
|
||||
handled_io_bits.insert(bit);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto wire : vector<Wire*>(module->wires()))
|
||||
{
|
||||
if (!wire->port_input && !wire->port_output)
|
||||
continue;
|
||||
|
||||
for (int index = 0; index < GetSize(wire); index++)
|
||||
{
|
||||
SigBit bit(wire, index);
|
||||
SigBit canonical_bit = sigmap(bit);
|
||||
|
||||
if (handled_io_bits.count(canonical_bit))
|
||||
continue;
|
||||
|
||||
if (wire->port_input && wire->port_output)
|
||||
log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit));
|
||||
|
||||
IdString buf_type, buf_port;
|
||||
|
||||
if (wire->port_output) {
|
||||
buf_type = "\\OUTBUF";
|
||||
buf_port = "\\D";
|
||||
} else if (clk_bits.count(canonical_bit)) {
|
||||
buf_type = "\\CLKBUF";
|
||||
buf_port = "\\Y";
|
||||
} else {
|
||||
buf_type = "\\INBUF";
|
||||
buf_port = "\\Y";
|
||||
}
|
||||
|
||||
Cell *c = module->addCell(NEW_ID, buf_type);
|
||||
SigBit new_bit = module->addWire(NEW_ID);
|
||||
c->setPort(buf_port, new_bit);
|
||||
pad_bits.push_back(make_pair(c, bit));
|
||||
rewrite_bits[canonical_bit] = new_bit;
|
||||
|
||||
log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
|
||||
}
|
||||
}
|
||||
|
||||
auto rewrite_function = [&](SigSpec &s) {
|
||||
for (auto &bit : s) {
|
||||
SigBit canonical_bit = sigmap(bit);
|
||||
if (rewrite_bits.count(canonical_bit))
|
||||
bit = rewrite_bits.at(canonical_bit);
|
||||
}
|
||||
};
|
||||
|
||||
module->rewrite_sigspecs(rewrite_function);
|
||||
|
||||
for (auto &it : pad_bits)
|
||||
it.first->setPort("\\PAD", it.second);
|
||||
handle_iobufs(module, clkbuf_mode);
|
||||
handle_clkint(module);
|
||||
}
|
||||
} Sf2IobsPass;
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@ struct SynthSf2Pass : public ScriptPass
|
|||
log(" -noiobs\n");
|
||||
log(" run synthesis in \"block mode\", i.e. do not insert IO buffers\n");
|
||||
log("\n");
|
||||
log(" -clkbuf\n");
|
||||
log(" insert direct PAD->global_net buffers\n");
|
||||
log("\n");
|
||||
log(" -retime\n");
|
||||
log(" run 'abc' with -dff option\n");
|
||||
log("\n");
|
||||
|
@ -73,7 +76,7 @@ struct SynthSf2Pass : public ScriptPass
|
|||
}
|
||||
|
||||
string top_opt, edif_file, vlog_file, json_file;
|
||||
bool flatten, retime, iobs;
|
||||
bool flatten, retime, iobs, clkbuf;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
|
@ -84,6 +87,7 @@ struct SynthSf2Pass : public ScriptPass
|
|||
flatten = true;
|
||||
retime = false;
|
||||
iobs = true;
|
||||
clkbuf = false;
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
|
@ -130,6 +134,10 @@ struct SynthSf2Pass : public ScriptPass
|
|||
iobs = false;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-clkbuf") {
|
||||
clkbuf = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -201,8 +209,10 @@ struct SynthSf2Pass : public ScriptPass
|
|||
|
||||
if (check_label("map_iobs"))
|
||||
{
|
||||
if (iobs || help_mode)
|
||||
run("sf2_iobs", "(unless -noiobs)");
|
||||
if (help_mode)
|
||||
run("sf2_iobs [-clkbuf]", "(unless -noiobs)");
|
||||
else if (iobs)
|
||||
run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");
|
||||
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_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_32.vh))
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// LCU
|
||||
|
||||
(* techmap_celltype = "$lcu" *)
|
||||
module _80_xilinx_lcu (P, G, CI, CO);
|
||||
parameter WIDTH = 2;
|
||||
|
@ -28,10 +31,78 @@ module _80_xilinx_lcu (P, G, CI, CO);
|
|||
|
||||
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] S = P & ~G;
|
||||
|
||||
genvar i;
|
||||
generate for (i = 0; i < WIDTH; i = i + 1) begin:slice
|
||||
MUXCY muxcy (
|
||||
.CI(C[i]),
|
||||
|
@ -40,8 +111,28 @@ module _80_xilinx_lcu (P, G, CI, CO);
|
|||
.O(CO[i])
|
||||
);
|
||||
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
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// ALU
|
||||
|
||||
(* techmap_celltype = "$alu" *)
|
||||
module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
||||
parameter A_SIGNED = 0;
|
||||
|
@ -49,6 +140,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
|||
parameter A_WIDTH = 1;
|
||||
parameter B_WIDTH = 1;
|
||||
parameter Y_WIDTH = 1;
|
||||
parameter _TECHMAP_CONSTVAL_CI_ = 0;
|
||||
parameter _TECHMAP_CONSTMSK_CI_ = 0;
|
||||
|
||||
input [A_WIDTH-1:0] A;
|
||||
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] BB = BI ? ~B_buf : B_buf;
|
||||
|
||||
wire [Y_WIDTH-1:0] P = AA ^ BB;
|
||||
wire [Y_WIDTH-1:0] G = AA & BB;
|
||||
wire [Y_WIDTH-1:0] C = {CO, CI};
|
||||
wire [Y_WIDTH-1:0] S = P & ~G;
|
||||
genvar i;
|
||||
|
||||
`ifdef _CLB_CARRY
|
||||
|
||||
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;
|
||||
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
|
||||
MUXCY muxcy (
|
||||
.CI(C[i]),
|
||||
.DI(G[i]),
|
||||
.DI(DI[i]),
|
||||
.S(S[i]),
|
||||
.O(CO[i])
|
||||
);
|
||||
|
@ -86,6 +352,8 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
|
|||
);
|
||||
end endgenerate
|
||||
|
||||
assign X = P;
|
||||
`endif
|
||||
|
||||
assign X = S;
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
`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
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
module \$__SHREG_ (input C, input D, input E, output Q);
|
||||
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.
|
||||
// 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];
|
||||
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);
|
||||
parameter [0:0] INIT = 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
|
||||
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 (
|
||||
output DPO, SPO,
|
||||
input D, WCLK, WE,
|
||||
|
|
|
@ -115,7 +115,7 @@ function xtract_cell_decl()
|
|||
xtract_cell_decl PS7
|
||||
xtract_cell_decl PULLDOWN
|
||||
xtract_cell_decl PULLUP
|
||||
# xtract_cell_decl RAM128X1D
|
||||
xtract_cell_decl RAM128X1D
|
||||
xtract_cell_decl RAM128X1S
|
||||
xtract_cell_decl RAM256X1S
|
||||
xtract_cell_decl RAM32M
|
||||
|
@ -124,7 +124,7 @@ function xtract_cell_decl()
|
|||
xtract_cell_decl RAM32X1S_1
|
||||
xtract_cell_decl RAM32X2S
|
||||
xtract_cell_decl RAM64M
|
||||
# xtract_cell_decl RAM64X1D
|
||||
xtract_cell_decl RAM64X1D
|
||||
xtract_cell_decl RAM64X1S
|
||||
xtract_cell_decl RAM64X1S_1
|
||||
xtract_cell_decl RAM64X2S
|
||||
|
|
|
@ -3695,6 +3695,25 @@ module RAM128X1S (...);
|
|||
input A0, A1, A2, A3, A4, A5, A6, D, WCLK, WE;
|
||||
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 (...);
|
||||
parameter [255:0] INIT = 256'h0;
|
||||
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(" (this feature is experimental and incomplete)\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(" 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");
|
||||
|
@ -90,11 +96,11 @@ struct SynthXilinxPass : public Pass
|
|||
log(" coarse:\n");
|
||||
log(" synth -run coarse\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(" techmap -map +/xilinx/brams_map.v\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(" techmap -map +/xilinx/drams_map.v\n");
|
||||
log("\n");
|
||||
|
@ -106,15 +112,17 @@ struct SynthXilinxPass : public Pass
|
|||
log(" opt -full\n");
|
||||
log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\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("\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("\n");
|
||||
log(" map_cells:\n");
|
||||
log(" techmap -map +/xilinx/cells_map.v (with -D NO_LUT in vpr mode)\n");
|
||||
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT\n");
|
||||
log(" techmap -map +/xilinx/cells_map.v\n");
|
||||
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT\n");
|
||||
log(" clean\n");
|
||||
log("\n");
|
||||
log(" check:\n");
|
||||
|
@ -138,6 +146,8 @@ struct SynthXilinxPass : public Pass
|
|||
bool flatten = false;
|
||||
bool retime = false;
|
||||
bool vpr = false;
|
||||
bool nobram = false;
|
||||
bool nodram = false;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
|
@ -174,6 +184,14 @@ struct SynthXilinxPass : public Pass
|
|||
vpr = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nobram") {
|
||||
nobram = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nodram") {
|
||||
nodram = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -188,9 +206,18 @@ struct SynthXilinxPass : public Pass
|
|||
|
||||
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/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()));
|
||||
}
|
||||
|
||||
|
@ -207,14 +234,18 @@ struct SynthXilinxPass : public Pass
|
|||
|
||||
if (check_label(active, run_from, run_to, "bram"))
|
||||
{
|
||||
Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
|
||||
Pass::call(design, "techmap -map +/xilinx/brams_map.v");
|
||||
if (!nobram) {
|
||||
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"))
|
||||
{
|
||||
Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
|
||||
Pass::call(design, "techmap -map +/xilinx/drams_map.v");
|
||||
if (!nodram) {
|
||||
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"))
|
||||
|
@ -224,8 +255,16 @@ struct SynthXilinxPass : public Pass
|
|||
Pass::call(design, "dffsr2dff");
|
||||
Pass::call(design, "dff2dffe");
|
||||
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, "techmap -map +/xilinx/ff_map.v");
|
||||
Pass::call(design, "hierarchy -check");
|
||||
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, "clean");
|
||||
Pass::call(design, "techmap -map +/xilinx/lut_map.v");
|
||||
}
|
||||
|
||||
if (check_label(active, run_from, run_to, "map_cells"))
|
||||
{
|
||||
Pass::call(design, "techmap -map +/xilinx/cells_map.v");
|
||||
if (vpr)
|
||||
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, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT");
|
||||
Pass::call(design, "clean");
|
||||
}
|
||||
|
||||
|
@ -254,7 +292,7 @@ struct SynthXilinxPass : public Pass
|
|||
if (check_label(active, run_from, run_to, "edif"))
|
||||
{
|
||||
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"))
|
||||
{
|
||||
|
|
|
@ -6,7 +6,6 @@ code_hdl_models_d_latch_gates.v combinational loop
|
|||
code_hdl_models_dff_async_reset.v $adff
|
||||
code_hdl_models_tff_async_reset.v $adff
|
||||
code_hdl_models_uart.v $adff
|
||||
code_specman_switch_fabric.v subfield assignment (bits() <= ...)
|
||||
code_tidbits_asyn_reset.v $adff
|
||||
code_tidbits_reg_seq_example.v $adff
|
||||
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 out4 = test4(in);
|
||||
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.
|
||||
arraycells.v inst id[0] of
|
||||
dff_different_styles.v
|
||||
dff_init.v Initial value not supported
|
||||
generate.v combinational loop
|
||||
hierdefparam.v inst id[0] of
|
||||
i2c_master_tests.v $adff
|
||||
|
@ -12,7 +13,6 @@ multiplier.v inst id[0] of
|
|||
muxtree.v drops modules
|
||||
omsp_dbg_uart.v $adff
|
||||
operators.v $pow
|
||||
paramods.v subfield assignment (bits() <= ...)
|
||||
partsel.v drops modules
|
||||
process.v drops modules
|
||||
realexpr.v drops modules
|
||||
|
|
|
@ -8,7 +8,7 @@ verbose=false
|
|||
keeprunning=false
|
||||
makejmode=false
|
||||
frontend="verilog"
|
||||
backend_opts="-noattr -noexpr"
|
||||
backend_opts="-noattr -noexpr -siminit"
|
||||
autotb_opts=""
|
||||
include_opts=""
|
||||
xinclude_opts=""
|
||||
|
@ -49,7 +49,7 @@ while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do
|
|||
r)
|
||||
backend_opts="$backend_opts -norename" ;;
|
||||
e)
|
||||
backend_opts="$( echo " $backend_opts " | sed 's, -noexpr ,,; s,^ ,,; s, $,,;'; )" ;;
|
||||
backend_opts="$( echo " $backend_opts " | sed 's, -noexpr , ,; s,^ ,,; s, $,,;'; )" ;;
|
||||
f)
|
||||
frontend="$OPTARG" ;;
|
||||
s)
|
||||
|
@ -175,7 +175,7 @@ do
|
|||
if [ -n "$firrtl2verilog" ]; 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
|
||||
$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
|
||||
fi
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue