mirror of
https://github.com/YosysHQ/yosys.git
synced 2026-10-06 10:03:36 +02:00
Move init values across barriers.
This commit is contained in:
@@ -143,6 +143,64 @@ struct FfInitVals
|
||||
remove_init(bit);
|
||||
}
|
||||
|
||||
// Move $barrier output init value to it's input
|
||||
void move_barrier_inits(RTLIL::Module *module)
|
||||
{
|
||||
dict<RTLIL::SigBit, RTLIL::SigBit> next;
|
||||
for (auto cell : module->cells()) {
|
||||
if (cell->type != ID($barrier))
|
||||
continue;
|
||||
RTLIL::SigSpec sig_y = (*sigmap)(cell->getPort(ID::Y)), sig_a = cell->getPort(ID::A);
|
||||
for (int i = 0; i < GetSize(sig_y); i++)
|
||||
next[sig_y[i]] = sig_a[i];
|
||||
}
|
||||
pool<RTLIL::SigBit> inputs = input_nets(module), moved;
|
||||
for (auto [from, to] : next) {
|
||||
RTLIL::State val = (*this)(from);
|
||||
if (val == State::Sx)
|
||||
continue;
|
||||
moved.insert(from);
|
||||
for (int i = 0; i < GetSize(next) && next.count((*sigmap)(to)); i++)
|
||||
to = next.at((*sigmap)(to));
|
||||
RTLIL::SigBit to_net = (*sigmap)(to);
|
||||
if (to_net.wire == nullptr || inputs.count(to_net))
|
||||
continue;
|
||||
RTLIL::State to_val = (*this)(to);
|
||||
if (to_val == State::Sx)
|
||||
set_init(to, val);
|
||||
else if (to_val != val)
|
||||
log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
|
||||
log_signal(to), log_signal(from), log_signal(val), log_signal(to_val));
|
||||
}
|
||||
remove_net_inits(module, moved);
|
||||
}
|
||||
|
||||
pool<RTLIL::SigBit> input_nets(RTLIL::Module *module) const
|
||||
{
|
||||
pool<RTLIL::SigBit> nets;
|
||||
for (auto wire : module->wires())
|
||||
if (wire->port_input)
|
||||
for (auto bit : (*sigmap)(wire))
|
||||
nets.insert(bit);
|
||||
return nets;
|
||||
}
|
||||
|
||||
void remove_net_inits(RTLIL::Module *module, const pool<RTLIL::SigBit> &nets)
|
||||
{
|
||||
for (auto bit : nets)
|
||||
initbits.erase(bit);
|
||||
for (auto wire : module->wires()) {
|
||||
auto it = wire->attributes.find(ID::init);
|
||||
if (it == wire->attributes.end())
|
||||
continue;
|
||||
for (int i = 0; i < GetSize(wire) && i < GetSize(it->second); i++)
|
||||
if (nets.count((*sigmap)(RTLIL::SigBit(wire, i))))
|
||||
it->second.set(i, State::Sx);
|
||||
if (it->second.is_fully_undef())
|
||||
wire->attributes.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
initbits.clear();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/ffinit.h"
|
||||
#include <algorithm>
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
@@ -455,6 +456,11 @@ struct OptBarriersPass : public Pass {
|
||||
}
|
||||
module->new_connections(new_connections);
|
||||
}
|
||||
|
||||
// Init values belong to the driver side of the barriers
|
||||
SigMap init_sigmap(module);
|
||||
FfInitVals initvals(&init_sigmap, module);
|
||||
initvals.move_barrier_inits(module);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,3 +166,53 @@ design -pop
|
||||
# With barriers they aren't
|
||||
prep -barriers
|
||||
select -assert-none w:c %ci1 w:d %ci1 %i
|
||||
|
||||
design -reset
|
||||
|
||||
# init on FF output
|
||||
read_verilog <<EOT
|
||||
module top(input clk, input d, output reg q = 1'b1);
|
||||
always @(posedge clk) q <= d;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
proc
|
||||
optbarriers
|
||||
select -assert-count 1 t:$barrier
|
||||
select -assert-count 1 t:$dff %co:+[Q] w:* %i a:init %i
|
||||
select -assert-none w:q a:init %i
|
||||
|
||||
design -reset
|
||||
|
||||
# init on alias
|
||||
read_verilog <<EOT
|
||||
module top(input clk, input d, output reg q = 1'b1, output w);
|
||||
assign w = q;
|
||||
always @(posedge clk) q <= d;
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
setattr -set init 1'b1 w:w
|
||||
optbarriers -noconns
|
||||
select -assert-none t:$barrier %co:+[Y] w:* %i a:init %i
|
||||
|
||||
design -reset
|
||||
|
||||
# Init on input port
|
||||
read_rtlil <<EOT
|
||||
module \top
|
||||
wire input 1 \i
|
||||
attribute \init 1'1
|
||||
wire output 2 \y
|
||||
wire $a
|
||||
connect $a \i
|
||||
cell $barrier \b
|
||||
parameter \WIDTH 1
|
||||
connect \A $a
|
||||
connect \Y \y
|
||||
end
|
||||
end
|
||||
EOT
|
||||
optbarriers
|
||||
opt_clean
|
||||
select -assert-none w:i a:init %i
|
||||
|
||||
Reference in New Issue
Block a user