mirror of
https://github.com/YosysHQ/yosys
synced 2025-07-25 13:47:02 +00:00
Merge pull request #1568 from YosysHQ/eddie/fix_zinit
zinit: fixes for $_DFF_[NP][NP][01]_and $adff cells with init = 1'b1
This commit is contained in:
commit
f44b287f8e
2 changed files with 90 additions and 17 deletions
|
@ -57,8 +57,7 @@ struct ZinitPass : public Pass {
|
||||||
for (auto module : design->selected_modules())
|
for (auto module : design->selected_modules())
|
||||||
{
|
{
|
||||||
SigMap sigmap(module);
|
SigMap sigmap(module);
|
||||||
dict<SigBit, State> initbits;
|
dict<SigBit, std::pair<State,SigBit>> initbits;
|
||||||
pool<SigBit> donebits;
|
|
||||||
|
|
||||||
for (auto wire : module->selected_wires())
|
for (auto wire : module->selected_wires())
|
||||||
{
|
{
|
||||||
|
@ -67,7 +66,6 @@ struct ZinitPass : public Pass {
|
||||||
|
|
||||||
SigSpec wirebits = sigmap(wire);
|
SigSpec wirebits = sigmap(wire);
|
||||||
Const initval = wire->attributes.at(ID::init);
|
Const initval = wire->attributes.at(ID::init);
|
||||||
wire->attributes.erase(ID::init);
|
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
|
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
|
||||||
{
|
{
|
||||||
|
@ -78,22 +76,25 @@ struct ZinitPass : public Pass {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (initbits.count(bit)) {
|
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_error("Conflicting init values for signal %s (%s = %s != %s).\n",
|
||||||
log_signal(bit), log_signal(SigBit(wire, i)),
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
initbits[bit] = val;
|
initbits[bit] = std::make_pair(val,SigBit(wire,i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pool<IdString> dff_types = {
|
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($_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_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
|
||||||
ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
|
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_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_)
|
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++) {
|
for (int i = 0; i < GetSize(sig_q); i++) {
|
||||||
if (initbits.count(sig_q[i])) {
|
if (initbits.count(sig_q[i])) {
|
||||||
initval.bits.push_back(initbits.at(sig_q[i]));
|
const auto &d = initbits.at(sig_q[i]);
|
||||||
donebits.insert(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
|
} else
|
||||||
initval.bits.push_back(all_mode ? State::S0 : State::Sx);
|
initval.bits.push_back(all_mode ? State::S0 : State::Sx);
|
||||||
}
|
}
|
||||||
|
@ -123,11 +126,11 @@ struct ZinitPass : public Pass {
|
||||||
initwire->attributes[ID::init] = initval;
|
initwire->attributes[ID::init] = initval;
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(initwire); i++)
|
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]);
|
sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
|
||||||
module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[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
|
else
|
||||||
{
|
{
|
||||||
|
@ -139,11 +142,24 @@ struct ZinitPass : public Pass {
|
||||||
|
|
||||||
cell->setPort(ID::D, sig_d);
|
cell->setPort(ID::D, sig_d);
|
||||||
cell->setPort(ID::Q, initwire);
|
cell->setPort(ID::Q, initwire);
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &it : initbits)
|
if (cell->type == ID($adff)) {
|
||||||
if (donebits.count(it.first) == 0)
|
auto val = cell->getParam(ID::ARST_VALUE);
|
||||||
log_error("Failed to handle init bit %s = %s.\n", log_signal(it.first), log_signal(it.second));
|
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;
|
} ZinitPass;
|
||||||
|
|
57
tests/techmap/zinit.ys
Normal file
57
tests/techmap/zinit.ys
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue