aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--frontends/ast/simplify.cc28
-rw-r--r--frontends/verilog/verilog_parser.y3
-rw-r--r--passes/techmap/zinit.cc50
-rw-r--r--tests/svtypes/typedef_package.sv11
-rw-r--r--tests/techmap/zinit.ys57
5 files changed, 126 insertions, 23 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index b87af0f8c..ced5e5cf9 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -420,9 +420,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
current_scope[node->str] = node;
for (auto enode : node->children) {
log_assert(enode->type==AST_ENUM_ITEM);
- if (current_scope.count(enode->str) == 0) {
+ if (current_scope.count(enode->str) == 0)
current_scope[enode->str] = enode;
- }
+ else
+ log_file_error(filename, location.first_line, "enum item %s already exists\n", enode->str.c_str());
}
}
}
@@ -441,6 +442,29 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
}
+ // create name resolution entries for all objects with names
+ if (type == AST_PACKAGE) {
+ //add names to package scope
+ for (size_t i = 0; i < children.size(); i++) {
+ AstNode *node = children[i];
+ // these nodes appear at the top level in a package and can define names
+ if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF) {
+ current_scope[node->str] = node;
+ }
+ if (node->type == AST_ENUM) {
+ current_scope[node->str] = node;
+ for (auto enode : node->children) {
+ log_assert(enode->type==AST_ENUM_ITEM);
+ if (current_scope.count(enode->str) == 0)
+ current_scope[enode->str] = enode;
+ else
+ log_file_error(filename, location.first_line, "enum item %s already exists in package\n", enode->str.c_str());
+ }
+ }
+ }
+ }
+
+
auto backup_current_block = current_block;
auto backup_current_block_child = current_block_child;
auto backup_current_top_block = current_top_block;
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index bd51aa12b..76373c2e4 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -521,7 +521,8 @@ package_body:
package_body_stmt:
typedef_decl |
- localparam_decl;
+ localparam_decl |
+ param_decl;
interface:
TOK_INTERFACE {
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc
index a427c4987..9eb47ff6d 100644
--- a/passes/techmap/zinit.cc
+++ b/passes/techmap/zinit.cc
@@ -57,8 +57,7 @@ struct ZinitPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, State> initbits;
- pool<SigBit> donebits;
+ dict<SigBit, std::pair<State,SigBit>> initbits;
for (auto wire : module->selected_wires())
{
@@ -67,7 +66,6 @@ struct ZinitPass : public Pass {
SigSpec wirebits = sigmap(wire);
Const initval = wire->attributes.at(ID::init);
- wire->attributes.erase(ID::init);
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
{
@@ -78,22 +76,25 @@ struct ZinitPass : public Pass {
continue;
if (initbits.count(bit)) {
- if (initbits.at(bit) != val)
+ if (initbits.at(bit).first != val)
log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
log_signal(bit), log_signal(SigBit(wire, i)),
- log_signal(val), log_signal(initbits.at(bit)));
+ log_signal(val), log_signal(initbits.at(bit).first));
continue;
}
- initbits[bit] = val;
+ initbits[bit] = std::make_pair(val,SigBit(wire,i));
}
}
pool<IdString> dff_types = {
- ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($adff),
+ // FIXME: It would appear that supporting
+ // $dffsr/$_DFFSR_* would require a new
+ // cell type where S has priority over R
+ ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff),
ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
- ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
- ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
+ /*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
+ ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/
ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)
};
@@ -113,8 +114,10 @@ struct ZinitPass : public Pass {
for (int i = 0; i < GetSize(sig_q); i++) {
if (initbits.count(sig_q[i])) {
- initval.bits.push_back(initbits.at(sig_q[i]));
- donebits.insert(sig_q[i]);
+ const auto &d = initbits.at(sig_q[i]);
+ initval.bits.push_back(d.first);
+ const auto &b = d.second;
+ b.wire->attributes.at(ID::init)[b.offset] = State::Sx;
} else
initval.bits.push_back(all_mode ? State::S0 : State::Sx);
}
@@ -123,11 +126,11 @@ struct ZinitPass : public Pass {
initwire->attributes[ID::init] = initval;
for (int i = 0; i < GetSize(initwire); i++)
- if (initval.bits.at(i) == State::S1)
+ if (initval[i] == State::S1)
{
sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
- initwire->attributes[ID::init].bits.at(i) = State::S0;
+ initwire->attributes[ID::init][i] = State::S0;
}
else
{
@@ -139,11 +142,24 @@ struct ZinitPass : public Pass {
cell->setPort(ID::D, sig_d);
cell->setPort(ID::Q, initwire);
- }
- for (auto &it : initbits)
- if (donebits.count(it.first) == 0)
- log_error("Failed to handle init bit %s = %s.\n", log_signal(it.first), log_signal(it.second));
+ if (cell->type == ID($adff)) {
+ auto val = cell->getParam(ID::ARST_VALUE);
+ for (int i = 0; i < GetSize(initwire); i++)
+ if (initval[i] == State::S1)
+ val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
+ cell->setParam(ID::ARST_VALUE, std::move(val));
+ }
+ else if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
+ ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
+ {
+ if (initval == State::S1) {
+ std::string t = cell->type.str();
+ t[8] = (t[8] == '0' ? '1' : '0');
+ cell->type = t;
+ }
+ }
+ }
}
}
} ZinitPass;
diff --git a/tests/svtypes/typedef_package.sv b/tests/svtypes/typedef_package.sv
index 57a78c53a..2d83742c5 100644
--- a/tests/svtypes/typedef_package.sv
+++ b/tests/svtypes/typedef_package.sv
@@ -1,6 +1,9 @@
package pkg;
typedef logic [7:0] uint8_t;
- typedef enum logic [7:0] {bb=8'hBB} enum8_t;
+ typedef enum logic [7:0] {bb=8'hBB, cc=8'hCC} enum8_t;
+
+ localparam uint8_t PCONST = cc;
+ parameter uint8_t PCONST_COPY = PCONST;
endpackage
module top;
@@ -8,7 +11,9 @@ module top;
(* keep *) pkg::uint8_t a = 8'hAA;
(* keep *) pkg::enum8_t b_enum = pkg::bb;
- always @* assert(a == 8'hAA);
- always @* assert(b_enum == 8'hBB);
+ always_comb assert(a == 8'hAA);
+ always_comb assert(b_enum == 8'hBB);
+ always_comb assert(pkg::PCONST == pkg::cc);
+ always_comb assert(pkg::PCONST_COPY == pkg::cc);
endmodule
diff --git a/tests/techmap/zinit.ys b/tests/techmap/zinit.ys
new file mode 100644
index 000000000..18b17621f
--- /dev/null
+++ b/tests/techmap/zinit.ys
@@ -0,0 +1,57 @@
+read_verilog -icells <<EOT
+module top(input C, R, input [1:0] D, (* init = {2'b10, 2'b01, 1'b1, {8{1'b1}}} *) output [12:0] Q);
+
+(* init = 1'b1 *)
+wire unused;
+
+$_DFF_NN0_ dff0 (.C(C), .D(D[0]), .R(R), .Q(Q[0]));
+$_DFF_NN1_ dff1 (.C(C), .D(D[0]), .R(R), .Q(Q[1]));
+$_DFF_NP0_ dff2 (.C(C), .D(D[0]), .R(R), .Q(Q[2]));
+$_DFF_NP1_ dff3 (.C(C), .D(D[0]), .R(R), .Q(Q[3]));
+$_DFF_PN0_ dff4 (.C(C), .D(D[0]), .R(R), .Q(Q[4]));
+$_DFF_PN1_ dff5 (.C(C), .D(D[0]), .R(R), .Q(Q[5]));
+$_DFF_PP0_ dff6 (.C(C), .D(D[0]), .R(R), .Q(Q[6]));
+$_DFF_PP1_ dff7 (.C(C), .D(D[0]), .R(R), .Q(Q[7]));
+
+$adff #(.WIDTH(2), .CLK_POLARITY(1), .ARST_POLARITY(1'b0), .ARST_VALUE(2'b10)) dff8 (.CLK(C), .ARST(R), .D(D), .Q(Q[10:9]));
+$adff #(.WIDTH(2), .CLK_POLARITY(0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'b01)) dff9 (.CLK(C), .ARST(R), .D(D), .Q(Q[12:11]));
+endmodule
+EOT
+equiv_opt -assert -map +/simcells.v -multiclock zinit
+design -load postopt
+
+select -assert-count 20 t:$_NOT_
+select -assert-count 1 w:unused a:init %i
+select -assert-count 1 w:Q a:init=13'bxxxx1xxxxxxxx %i
+select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$_DFF_??1_ %i
+select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$_DFF_??0_ %i
+
+
+design -reset
+read_verilog -icells <<EOT
+module top(input C, R, input [1:0] D, (* init = {2'bx0, 2'b0x, 1'b1, {8{1'b0}}} *) output [12:0] Q);
+
+(* init = 1'b1 *)
+wire unused;
+
+$_DFF_NN0_ dff0 (.C(C), .D(D[0]), .R(R), .Q(Q[0]));
+$_DFF_NN1_ dff1 (.C(C), .D(D[0]), .R(R), .Q(Q[1]));
+$_DFF_NP0_ dff2 (.C(C), .D(D[0]), .R(R), .Q(Q[2]));
+$_DFF_NP1_ dff3 (.C(C), .D(D[0]), .R(R), .Q(Q[3]));
+$_DFF_PN0_ dff4 (.C(C), .D(D[0]), .R(R), .Q(Q[4]));
+$_DFF_PN1_ dff5 (.C(C), .D(D[0]), .R(R), .Q(Q[5]));
+$_DFF_PP0_ dff6 (.C(C), .D(D[0]), .R(R), .Q(Q[6]));
+$_DFF_PP1_ dff7 (.C(C), .D(D[0]), .R(R), .Q(Q[7]));
+
+$adff #(.WIDTH(2), .CLK_POLARITY(1), .ARST_POLARITY(1'b0), .ARST_VALUE(2'b10)) dff8 (.CLK(C), .ARST(R), .D(D), .Q(Q[10:9]));
+$adff #(.WIDTH(2), .CLK_POLARITY(0), .ARST_POLARITY(1'b1), .ARST_VALUE(2'b01)) dff9 (.CLK(C), .ARST(R), .D(D), .Q(Q[12:11]));
+endmodule
+EOT
+equiv_opt -assert -map +/simcells.v -multiclock zinit
+design -load postopt
+
+select -assert-count 0 t:$_NOT_
+select -assert-count 1 w:unused a:init %i
+select -assert-count 1 w:Q a:init=13'bxxxx1xxxxxxxx %i
+select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$_DFF_??0_ %i
+select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$_DFF_??1_ %i