mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #1105 from YosysHQ/clifford/fixlogicinit
Improve handling of initial/default values
This commit is contained in:
commit
5a1f1caa44
|
@ -350,6 +350,10 @@ Verilog Attributes and non-standard features
|
||||||
through the synthesis. When entities are combined, a new |-separated
|
through the synthesis. When entities are combined, a new |-separated
|
||||||
string is created that contains all the string from the original entities.
|
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
|
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
|
||||||
the non-standard ``{* ... *}`` attribute syntax to set default attributes
|
the non-standard ``{* ... *}`` attribute syntax to set default attributes
|
||||||
for everything that comes after the ``{* ... *}`` statement. (Reset
|
for everything that comes after the ``{* ... *}`` statement. (Reset
|
||||||
|
|
|
@ -345,7 +345,13 @@ module_arg_opt_assignment:
|
||||||
if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
|
if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
|
||||||
AstNode *wire = new AstNode(AST_IDENTIFIER);
|
AstNode *wire = new AstNode(AST_IDENTIFIER);
|
||||||
wire->str = ast_stack.back()->children.back()->str;
|
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))));
|
ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));
|
||||||
else
|
else
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
|
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
|
||||||
|
@ -1360,7 +1366,12 @@ wire_name_and_opt_assign:
|
||||||
wire_name '=' expr {
|
wire_name '=' expr {
|
||||||
AstNode *wire = new AstNode(AST_IDENTIFIER);
|
AstNode *wire = new AstNode(AST_IDENTIFIER);
|
||||||
wire->str = ast_stack.back()->children.back()->str;
|
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))));
|
ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3))));
|
||||||
else
|
else
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3));
|
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3));
|
||||||
|
|
|
@ -591,6 +591,9 @@ struct HierarchyPass : public Pass {
|
||||||
log(" module instances when the width does not match the module port. This\n");
|
log(" module instances when the width does not match the module port. This\n");
|
||||||
log(" option disables this behavior.\n");
|
log(" option disables this behavior.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -nodefaults\n");
|
||||||
|
log(" do not resolve input port default values\n");
|
||||||
|
log("\n");
|
||||||
log(" -nokeep_asserts\n");
|
log(" -nokeep_asserts\n");
|
||||||
log(" per default this pass sets the \"keep\" attribute on all modules\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");
|
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 generate_mode = false;
|
||||||
bool keep_positionals = false;
|
bool keep_positionals = false;
|
||||||
bool keep_portwidths = false;
|
bool keep_portwidths = false;
|
||||||
|
bool nodefaults = false;
|
||||||
bool nokeep_asserts = false;
|
bool nokeep_asserts = false;
|
||||||
std::vector<std::string> generate_cells;
|
std::vector<std::string> generate_cells;
|
||||||
std::vector<generate_port_decl_t> generate_ports;
|
std::vector<generate_port_decl_t> generate_ports;
|
||||||
|
@ -712,6 +716,10 @@ struct HierarchyPass : public Pass {
|
||||||
keep_portwidths = true;
|
keep_portwidths = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-nodefaults") {
|
||||||
|
nodefaults = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-nokeep_asserts") {
|
if (args[argidx] == "-nokeep_asserts") {
|
||||||
nokeep_asserts = true;
|
nokeep_asserts = true;
|
||||||
continue;
|
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::set<Module*> blackbox_derivatives;
|
||||||
std::vector<Module*> design_modules = design->modules();
|
std::vector<Module*> design_modules = design->modules();
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -89,8 +89,7 @@ done
|
||||||
|
|
||||||
compile_and_run() {
|
compile_and_run() {
|
||||||
exe="$1"; output="$2"; shift 2
|
exe="$1"; output="$2"; shift 2
|
||||||
ext=${1##*.}
|
if [ "${2##*.}" == "sv" ]; then
|
||||||
if [ "$ext" == "sv" ]; then
|
|
||||||
language_gen="-g2012"
|
language_gen="-g2012"
|
||||||
else
|
else
|
||||||
language_gen="-g2005"
|
language_gen="-g2005"
|
||||||
|
@ -142,23 +141,25 @@ do
|
||||||
cd ${bn}.out
|
cd ${bn}.out
|
||||||
fn=$(basename $fn)
|
fn=$(basename $fn)
|
||||||
bn=$(basename $bn)
|
bn=$(basename $bn)
|
||||||
|
refext=v
|
||||||
|
|
||||||
rm -f ${bn}_ref.fir
|
rm -f ${bn}_ref.fir
|
||||||
if [[ "$ext" == "v" ]]; then
|
if [[ "$ext" == "v" ]]; then
|
||||||
egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext}
|
egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext}
|
||||||
elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then
|
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
|
else
|
||||||
cp ../${fn} ${bn}_ref.${ext}
|
refext=$ext
|
||||||
|
cp ../${fn} ${bn}_ref.${refext}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f ../${bn}_tb.v ]; then
|
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
|
else
|
||||||
cp ../${bn}_tb.v ${bn}_tb.v
|
cp ../${bn}_tb.v ${bn}_tb.v
|
||||||
fi
|
fi
|
||||||
if $genvcd; then sed -i 's,// \$dump,$dump,g' ${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/simlib.v \
|
||||||
"$toolsdir"/../../techlibs/common/simcells.v
|
"$toolsdir"/../../techlibs/common/simcells.v
|
||||||
if $genvcd; then mv testbench.vcd ${bn}_ref.vcd; fi
|
if $genvcd; then mv testbench.vcd ${bn}_ref.vcd; fi
|
||||||
|
@ -175,25 +176,25 @@ do
|
||||||
test_count=$(( test_count + 1 ))
|
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
|
touch ../${bn}.skip
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$scriptfiles" ]; then
|
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
|
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
|
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
|
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
|
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; 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.v
|
test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext}
|
||||||
if [ -n "$firrtl2verilog" ]; then
|
if [ -n "$firrtl2verilog" ]; then
|
||||||
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
|
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
|
||||||
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v
|
"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.${refext}
|
||||||
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
|
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
|
||||||
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v
|
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in New Issue