aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2019-06-19 13:53:07 +0200
committerGitHub <noreply@github.com>2019-06-19 13:53:07 +0200
commit5a1f1caa44fb3f4427813acab61aaecc06bae7ba (patch)
tree3cceea7d49a6ae44e5ab765e0bd11fecfee6b47b
parentc330379870a48209534807d1c021ce2a20ccf880 (diff)
parentfa5fc3f6afd9eb27c1f52244b60cbeb77aa2e26c (diff)
downloadyosys-5a1f1caa44fb3f4427813acab61aaecc06bae7ba.tar.gz
yosys-5a1f1caa44fb3f4427813acab61aaecc06bae7ba.tar.bz2
yosys-5a1f1caa44fb3f4427813acab61aaecc06bae7ba.zip
Merge pull request #1105 from YosysHQ/clifford/fixlogicinit
Improve handling of initial/default values
-rw-r--r--README.md4
-rw-r--r--frontends/verilog/verilog_parser.y15
-rw-r--r--passes/hierarchy/hierarchy.cc38
-rw-r--r--tests/simple/defvalue.sv22
-rwxr-xr-xtests/tools/autotest.sh29
5 files changed, 92 insertions, 16 deletions
diff --git a/README.md b/README.md
index 94ea9538f..637703a7f 100644
--- a/README.md
+++ b/README.md
@@ -350,6 +350,10 @@ Verilog Attributes and non-standard features
through the synthesis. When entities are combined, a new |-separated
string is created that contains all the string from the original entities.
+- The ``defaultvalue`` attribute is used to store default values for
+ module inputs. The attribute is attached to the input wire by the HDL
+ front-end when the input is declared with a default value.
+
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
the non-standard ``{* ... *}`` attribute syntax to set default attributes
for everything that comes after the ``{* ... *}`` statement. (Reset
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index ea8e457e8..ebb4369c3 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -345,7 +345,13 @@ module_arg_opt_assignment:
if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
AstNode *wire = new AstNode(AST_IDENTIFIER);
wire->str = ast_stack.back()->children.back()->str;
- if (ast_stack.back()->children.back()->is_reg)
+ if (ast_stack.back()->children.back()->is_input) {
+ AstNode *n = ast_stack.back()->children.back();
+ if (n->attributes.count("\\defaultvalue"))
+ delete n->attributes.at("\\defaultvalue");
+ n->attributes["\\defaultvalue"] = $2;
+ } else
+ if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic)
ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));
else
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
@@ -1360,7 +1366,12 @@ wire_name_and_opt_assign:
wire_name '=' expr {
AstNode *wire = new AstNode(AST_IDENTIFIER);
wire->str = ast_stack.back()->children.back()->str;
- if (astbuf1->is_reg)
+ if (astbuf1->is_input) {
+ if (astbuf1->attributes.count("\\defaultvalue"))
+ delete astbuf1->attributes.at("\\defaultvalue");
+ astbuf1->attributes["\\defaultvalue"] = $3;
+ } else
+ if (astbuf1->is_reg || astbuf1->is_logic)
ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3))));
else
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3));
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index 24e64a9b2..213437c01 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -591,6 +591,9 @@ struct HierarchyPass : public Pass {
log(" module instances when the width does not match the module port. This\n");
log(" option disables this behavior.\n");
log("\n");
+ log(" -nodefaults\n");
+ log(" do not resolve input port default values\n");
+ log("\n");
log(" -nokeep_asserts\n");
log(" per default this pass sets the \"keep\" attribute on all modules\n");
log(" that directly or indirectly contain one or more formal properties.\n");
@@ -645,6 +648,7 @@ struct HierarchyPass : public Pass {
bool generate_mode = false;
bool keep_positionals = false;
bool keep_portwidths = false;
+ bool nodefaults = false;
bool nokeep_asserts = false;
std::vector<std::string> generate_cells;
std::vector<generate_port_decl_t> generate_ports;
@@ -712,6 +716,10 @@ struct HierarchyPass : public Pass {
keep_portwidths = true;
continue;
}
+ if (args[argidx] == "-nodefaults") {
+ nodefaults = true;
+ continue;
+ }
if (args[argidx] == "-nokeep_asserts") {
nokeep_asserts = true;
continue;
@@ -940,6 +948,36 @@ struct HierarchyPass : public Pass {
}
}
+ if (!nodefaults)
+ {
+ dict<IdString, dict<IdString, Const>> defaults_db;
+
+ for (auto module : design->modules())
+ for (auto wire : module->wires())
+ if (wire->port_input && wire->attributes.count("\\defaultvalue"))
+ defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue");
+
+ for (auto module : design->modules())
+ for (auto cell : module->cells())
+ {
+ if (defaults_db.count(cell->type) == 0)
+ continue;
+
+ if (keep_positionals) {
+ bool found_positionals = false;
+ for (auto &conn : cell->connections())
+ if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9')
+ found_positionals = true;
+ if (found_positionals)
+ continue;
+ }
+
+ for (auto &it : defaults_db.at(cell->type))
+ if (!cell->hasPort(it.first))
+ cell->setPort(it.first, it.second);
+ }
+ }
+
std::set<Module*> blackbox_derivatives;
std::vector<Module*> design_modules = design->modules();
diff --git a/tests/simple/defvalue.sv b/tests/simple/defvalue.sv
new file mode 100644
index 000000000..b0a087ecb
--- /dev/null
+++ b/tests/simple/defvalue.sv
@@ -0,0 +1,22 @@
+module top(input clock, input [3:0] delta, output [3:0] cnt1, cnt2);
+ cnt #(1) foo (.clock, .cnt(cnt1), .delta);
+ cnt #(2) bar (.clock, .cnt(cnt2));
+endmodule
+
+module cnt #(
+ parameter integer initval = 0
+) (
+ input clock,
+ output logic [3:0] cnt = initval,
+`ifdef __ICARUS__
+ input [3:0] delta
+`else
+ input [3:0] delta = 10
+`endif
+);
+`ifdef __ICARUS__
+ assign (weak0, weak1) delta = 10;
+`endif
+ always @(posedge clock)
+ cnt <= cnt + delta;
+endmodule
diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh
index 23964a751..96d9cdda9 100755
--- a/tests/tools/autotest.sh
+++ b/tests/tools/autotest.sh
@@ -89,8 +89,7 @@ done
compile_and_run() {
exe="$1"; output="$2"; shift 2
- ext=${1##*.}
- if [ "$ext" == "sv" ]; then
+ if [ "${2##*.}" == "sv" ]; then
language_gen="-g2012"
else
language_gen="-g2005"
@@ -142,23 +141,25 @@ do
cd ${bn}.out
fn=$(basename $fn)
bn=$(basename $bn)
+ refext=v
rm -f ${bn}_ref.fir
if [[ "$ext" == "v" ]]; then
egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext}
elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then
- "$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.v"
+ "$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.${refext}"
else
- cp ../${fn} ${bn}_ref.${ext}
+ refext=$ext
+ cp ../${fn} ${bn}_ref.${refext}
fi
if [ ! -f ../${bn}_tb.v ]; then
- "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v
+ "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext}
else
cp ../${bn}_tb.v ${bn}_tb.v
fi
if $genvcd; then sed -i 's,// \$dump,$dump,g' ${bn}_tb.v; fi
- compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.v $libs \
+ compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.${refext} $libs \
"$toolsdir"/../../techlibs/common/simlib.v \
"$toolsdir"/../../techlibs/common/simcells.v
if $genvcd; then mv testbench.vcd ${bn}_ref.vcd; fi
@@ -175,25 +176,25 @@ do
test_count=$(( test_count + 1 ))
}
- if [ "$frontend" = "verific" -o "$frontend" = "verific_gates" ] && grep -q VERIFIC-SKIP ${bn}_ref.v; then
+ if [ "$frontend" = "verific" -o "$frontend" = "verific_gates" ] && grep -q VERIFIC-SKIP ${bn}_ref.${refext}; then
touch ../${bn}.skip
return
fi
if [ -n "$scriptfiles" ]; then
- test_passes -f "$frontend $include_opts" ${bn}_ref.v $scriptfiles
+ test_passes -f "$frontend $include_opts" ${bn}_ref.${refext} $scriptfiles
elif [ -n "$scriptopt" ]; then
- test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.v
+ test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.${refext}
elif [ "$frontend" = "verific" ]; then
- test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -all; opt; memory;;"
+ test_passes -p "verific -vlog2k ${bn}_ref.${refext}; verific -import -all; opt; memory;;"
elif [ "$frontend" = "verific_gates" ]; then
- test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -gates -all; opt; memory;;"
+ test_passes -p "verific -vlog2k ${bn}_ref.${refext}; verific -import -gates -all; opt; memory;;"
else
- test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.v
- test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.v
+ test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.${refext}
+ test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext}
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
+ "$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.${refext}
$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