aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--frontends/ast/ast.cc35
-rw-r--r--frontends/ast/ast.h2
-rw-r--r--frontends/ast/simplify.cc11
-rw-r--r--frontends/verilog/verilog_frontend.cc29
-rw-r--r--passes/opt/wreduce.cc27
-rw-r--r--techlibs/xilinx/cells_xtra.sh12
-rw-r--r--techlibs/xilinx/cells_xtra.v43
7 files changed, 115 insertions, 44 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 5a1bae7a7..d48996167 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -45,7 +45,7 @@ namespace AST {
// instantiate global variables (private API)
namespace AST_INTERNAL {
- bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
+ bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
AstNode *current_ast, *current_ast_mod;
std::map<std::string, AstNode*> current_scope;
@@ -431,9 +431,12 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
break;
case AST_RANGE:
- if (range_valid)
- fprintf(f, "[%d:%d]", range_left, range_right);
- else {
+ if (range_valid) {
+ if (range_swapped)
+ fprintf(f, "[%d:%d]", range_right, range_left);
+ else
+ fprintf(f, "[%d:%d]", range_left, range_right);
+ } else {
for (auto child : children) {
fprintf(f, "%c", first ? '[' : ':');
child->dumpVlog(f, "");
@@ -562,7 +565,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_CONCAT:
fprintf(f, "{");
- for (auto child : children) {
+ for (int i = GetSize(children)-1; i >= 0; i--) {
+ auto child = children[i];
if (!first)
fprintf(f, ", ");
child->dumpVlog(f, "");
@@ -926,23 +930,28 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
ast_before_simplify = ast->clone();
if (flag_dump_ast1) {
- log("Dumping Verilog AST before simplification:\n");
+ log("Dumping AST before simplification:\n");
ast->dumpAst(NULL, " ");
log("--- END OF AST DUMP ---\n");
}
+ if (flag_dump_vlog1) {
+ log("Dumping Verilog AST before simplification:\n");
+ ast->dumpVlog(NULL, " ");
+ log("--- END OF AST DUMP ---\n");
+ }
if (!defer)
{
while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { }
if (flag_dump_ast2) {
- log("Dumping Verilog AST after simplification:\n");
+ log("Dumping AST after simplification:\n");
ast->dumpAst(NULL, " ");
log("--- END OF AST DUMP ---\n");
}
- if (flag_dump_vlog) {
- log("Dumping Verilog AST (as requested by dump_vlog option):\n");
+ if (flag_dump_vlog2) {
+ log("Dumping Verilog AST after simplification:\n");
ast->dumpVlog(NULL, " ");
log("--- END OF AST DUMP ---\n");
}
@@ -1016,14 +1025,15 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
}
// create AstModule instances for all modules in the AST tree and add them to 'design'
-void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil,
+void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil,
bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire)
{
current_ast = ast;
flag_dump_ast1 = dump_ast1;
flag_dump_ast2 = dump_ast2;
flag_no_dump_ptr = no_dump_ptr;
- flag_dump_vlog = dump_vlog;
+ flag_dump_vlog1 = dump_vlog1;
+ flag_dump_vlog2 = dump_vlog2;
flag_dump_rtlil = dump_rtlil;
flag_nolatches = nolatches;
flag_nomeminit = nomeminit;
@@ -1357,7 +1367,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
current_ast = NULL;
flag_dump_ast1 = false;
flag_dump_ast2 = false;
- flag_dump_vlog = false;
+ flag_dump_vlog1 = false;
+ flag_dump_vlog2 = false;
flag_nolatches = nolatches;
flag_nomeminit = nomeminit;
flag_nomem2reg = nomem2reg;
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 8b185ff51..ddd59d4be 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -282,7 +282,7 @@ namespace AST
};
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
- void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil, bool nolatches, bool nomeminit,
+ void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit,
bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire);
// parametric modules are supported directly by the AST library
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index d525c6b8a..63b71b800 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -138,9 +138,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
int mem_width, mem_size, addr_bits;
node->meminfo(mem_width, mem_size, addr_bits);
+ int data_range_left = node->children[0]->range_left;
+ int data_range_right = node->children[0]->range_right;
+
+ if (node->children[0]->range_swapped)
+ std::swap(data_range_left, data_range_right);
+
for (int i = 0; i < mem_size; i++) {
AstNode *reg = new AstNode(AST_WIRE, new AstNode(AST_RANGE,
- mkconst_int(mem_width-1, true), mkconst_int(0, true)));
+ mkconst_int(data_range_left, true), mkconst_int(data_range_right, true)));
reg->str = stringf("%s[%d]", node->str.c_str(), i);
reg->is_reg = true;
reg->is_signed = node->is_signed;
@@ -976,6 +982,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
int data_range_left = id2ast->children[0]->range_left;
int data_range_right = id2ast->children[0]->range_right;
+ if (id2ast->children[0]->range_swapped)
+ std::swap(data_range_left, data_range_right);
+
std::stringstream sstr;
sstr << "$mem2bits$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++);
std::string wire_id = sstr.str();
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index aeea36a2b..504f8b3f3 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -81,6 +81,9 @@ struct VerilogFrontend : public Frontend {
log(" -assert-assumes\n");
log(" treat all assume() statements like assert() statements\n");
log("\n");
+ log(" -debug\n");
+ log(" alias for -dump_ast1 -dump_ast2 -dump_vlog1 -dump_vlog2 -yydebug\n");
+ log("\n");
log(" -dump_ast1\n");
log(" dump abstract syntax tree (before simplification)\n");
log("\n");
@@ -90,7 +93,10 @@ struct VerilogFrontend : public Frontend {
log(" -no_dump_ptr\n");
log(" do not include hex memory addresses in dump (easier to diff dumps)\n");
log("\n");
- log(" -dump_vlog\n");
+ log(" -dump_vlog1\n");
+ log(" dump ast as Verilog code (before simplification)\n");
+ log("\n");
+ log(" -dump_vlog2\n");
log(" dump ast as Verilog code (after simplification)\n");
log("\n");
log(" -dump_rtlil\n");
@@ -197,7 +203,8 @@ struct VerilogFrontend : public Frontend {
bool flag_dump_ast1 = false;
bool flag_dump_ast2 = false;
bool flag_no_dump_ptr = false;
- bool flag_dump_vlog = false;
+ bool flag_dump_vlog1 = false;
+ bool flag_dump_vlog2 = false;
bool flag_dump_rtlil = false;
bool flag_nolatches = false;
bool flag_nomeminit = false;
@@ -258,6 +265,14 @@ struct VerilogFrontend : public Frontend {
assert_assumes_mode = true;
continue;
}
+ if (arg == "-debug") {
+ flag_dump_ast1 = true;
+ flag_dump_ast2 = true;
+ flag_dump_vlog1 = true;
+ flag_dump_vlog2 = true;
+ frontend_verilog_yydebug = true;
+ continue;
+ }
if (arg == "-dump_ast1") {
flag_dump_ast1 = true;
continue;
@@ -270,8 +285,12 @@ struct VerilogFrontend : public Frontend {
flag_no_dump_ptr = true;
continue;
}
- if (arg == "-dump_vlog") {
- flag_dump_vlog = true;
+ if (arg == "-dump_vlog1") {
+ flag_dump_vlog1 = true;
+ continue;
+ }
+ if (arg == "-dump_vlog2") {
+ flag_dump_vlog2 = true;
continue;
}
if (arg == "-dump_rtlil") {
@@ -410,7 +429,7 @@ struct VerilogFrontend : public Frontend {
if (flag_nodpi)
error_on_dpi_function(current_ast);
- AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, lib_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
+ AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, lib_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
if (!flag_nopp)
delete lexin;
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc
index 1f7222e49..52245ce3e 100644
--- a/passes/opt/wreduce.cc
+++ b/passes/opt/wreduce.cc
@@ -54,6 +54,7 @@ struct WreduceWorker
std::set<SigBit> work_queue_bits;
pool<SigBit> keep_bits;
dict<SigBit, State> init_bits;
+ pool<SigBit> remove_init_bits;
WreduceWorker(WreduceConfig *config, Module *module) :
config(config), module(module), mi(module) { }
@@ -164,6 +165,7 @@ struct WreduceWorker
{
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) {
module->connect(sig_q[i], State::S0);
+ remove_init_bits.insert(sig_q[i]);
sig_d.remove(i);
sig_q.remove(i);
continue;
@@ -171,6 +173,7 @@ struct WreduceWorker
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]);
+ remove_init_bits.insert(sig_q[i]);
sig_d.remove(i);
sig_q.remove(i);
continue;
@@ -178,6 +181,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]))) {
+ remove_init_bits.insert(sig_q[i]);
sig_d.remove(i);
sig_q.remove(i);
zero_ext = false;
@@ -387,13 +391,16 @@ struct WreduceWorker
void run()
{
+ // create a copy as mi.sigmap will be updated as we process the module
+ SigMap init_attr_sigmap = mi.sigmap;
+
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);
+ SigSpec initsig = init_attr_sigmap(w);
int width = std::min(GetSize(initval), GetSize(initsig));
for (int i = 0; i < width; i++)
init_bits[initsig[i]] = initval[i];
@@ -446,6 +453,24 @@ struct WreduceWorker
module->connect(nw, SigSpec(w).extract(0, GetSize(nw)));
module->swap_names(w, nw);
}
+
+ if (!remove_init_bits.empty()) {
+ for (auto w : module->wires()) {
+ if (w->attributes.count("\\init")) {
+ Const initval = w->attributes.at("\\init");
+ Const new_initval(State::Sx, GetSize(w));
+ SigSpec initsig = init_attr_sigmap(w);
+ int width = std::min(GetSize(initval), GetSize(initsig));
+ for (int i = 0; i < width; i++) {
+ log_dump(initsig[i], remove_init_bits.count(initsig[i]));
+ if (!remove_init_bits.count(initsig[i]))
+ new_initval[i] = initval[i];
+ }
+ w->attributes.at("\\init") = new_initval;
+ log_dump(w->name, initval, new_initval);
+ }
+ }
+ }
}
};
diff --git a/techlibs/xilinx/cells_xtra.sh b/techlibs/xilinx/cells_xtra.sh
index 46ababdea..3f8efeebd 100644
--- a/techlibs/xilinx/cells_xtra.sh
+++ b/techlibs/xilinx/cells_xtra.sh
@@ -7,6 +7,7 @@ function xtract_cell_decl()
{
for dir in $libdir/xeclib $libdir/retarget; do
[ -f $dir/$1.v ] || continue
+ [ -z "$2" ] || echo $2
egrep '^\s*((end)?module|parameter|input|inout|output|(end)?function|(end)?task)' $dir/$1.v |
sed -re '/UNPLACED/ d; /^\s*function/,/endfunction/ d; /^\s*task/,/endtask/ d;
s,//.*,,; s/#?\(.*/(...);/; s/^(input|output|parameter)/ \1/;
@@ -37,10 +38,10 @@ function xtract_cell_decl()
xtract_cell_decl BUFMR
xtract_cell_decl BUFMRCE
xtract_cell_decl BUFR
- xtract_cell_decl CAPTUREE2
+ xtract_cell_decl CAPTUREE2 "(* keep *)"
# xtract_cell_decl CARRY4
xtract_cell_decl CFGLUT5
- xtract_cell_decl DCIRESET
+ xtract_cell_decl DCIRESET "(* keep *)"
xtract_cell_decl DNA_PORT
xtract_cell_decl DSP48E1
xtract_cell_decl EFUSE_USR
@@ -67,10 +68,10 @@ function xtract_cell_decl()
xtract_cell_decl IBUFDS_GTE2
xtract_cell_decl IBUFDS_IBUFDISABLE
xtract_cell_decl IBUFDS_INTERMDISABLE
- xtract_cell_decl ICAPE2
+ xtract_cell_decl ICAPE2 "(* keep *)"
xtract_cell_decl IDDR
xtract_cell_decl IDDR_2CLK
- xtract_cell_decl IDELAYCTRL
+ xtract_cell_decl IDELAYCTRL "(* keep *)"
xtract_cell_decl IDELAYE2
xtract_cell_decl IN_FIFO
xtract_cell_decl IOBUF
@@ -112,7 +113,7 @@ function xtract_cell_decl()
xtract_cell_decl PHY_CONTROL
xtract_cell_decl PLLE2_ADV
xtract_cell_decl PLLE2_BASE
- xtract_cell_decl PS7
+ xtract_cell_decl PS7 "(* keep *)"
xtract_cell_decl PULLDOWN
xtract_cell_decl PULLUP
xtract_cell_decl RAM128X1D
@@ -137,6 +138,7 @@ function xtract_cell_decl()
#xtract_cell_decl SRL16E
#xtract_cell_decl SRLC32E
xtract_cell_decl STARTUPE2
+ xtract_cell_decl STARTUPE2 "(* keep *)"
xtract_cell_decl USR_ACCESSE2
xtract_cell_decl XADC
} > cells_xtra.new
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 6adad35ae..06c868080 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -114,6 +114,7 @@ module BUFR (...);
parameter SIM_DEVICE = "7SERIES";
endmodule
+(* keep *)
module CAPTUREE2 (...);
parameter ONESHOT = "TRUE";
input CAP;
@@ -130,6 +131,7 @@ module CFGLUT5 (...);
input CDI, CE, CLK;
endmodule
+(* keep *)
module DCIRESET (...);
output LOCKED;
input RST;
@@ -2102,6 +2104,7 @@ module IBUFDS_INTERMDISABLE (...);
input INTERMDISABLE;
endmodule
+(* keep *)
module ICAPE2 (...);
parameter [31:0] DEVICE_ID = 32'h04244093;
parameter ICAP_WIDTH = "X32";
@@ -2149,6 +2152,7 @@ module IDDR_2CLK (...);
input S;
endmodule
+(* keep *)
module IDELAYCTRL (...);
parameter SIM_DEVICE = "7SERIES";
output RDY;
@@ -3057,6 +3061,7 @@ module PLLE2_BASE (...);
input RST;
endmodule
+(* keep *)
module PS7 (...);
output DMA0DAVALID;
output DMA0DRREADY;
@@ -3688,6 +3693,17 @@ module PULLUP (...);
output O;
endmodule
+module RAM128X1D (...);
+ parameter [127:0] INIT = 128'h00000000000000000000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ output DPO, SPO;
+ input [6:0] A;
+ input [6:0] DPRA;
+ input D;
+ input WCLK;
+ input WE;
+endmodule
+
module RAM128X1S (...);
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@@ -3695,25 +3711,6 @@ 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;
@@ -3797,6 +3794,13 @@ module RAM64M (...);
input WE;
endmodule
+module RAM64X1D (...);
+ parameter [63:0] INIT = 64'h0000000000000000;
+ parameter [0:0] IS_WCLK_INVERTED = 1'b0;
+ output DPO, SPO;
+ input A0, A1, A2, A3, A4, A5, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5, WCLK, WE;
+endmodule
+
module RAM64X1S (...);
parameter [63:0] INIT = 64'h0000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@@ -3843,6 +3847,7 @@ module ROM64X1 (...);
input A0, A1, A2, A3, A4, A5;
endmodule
+(* keep *)
module STARTUPE2 (...);
parameter PROG_USR = "FALSE";
parameter real SIM_CCLK_FREQ = 0.0;