mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 17:15:33 +00:00
Merge branch 'YosysHQ:main' into main
This commit is contained in:
commit
9d3b7f7474
13 changed files with 1019 additions and 10 deletions
|
@ -5,7 +5,22 @@ YOSYS_NAMESPACE_BEGIN
|
|||
|
||||
namespace RTLIL {
|
||||
|
||||
class KernelRtlilTest : public testing::Test {};
|
||||
struct SafePrintToStringParamName {
|
||||
template <class ParamType>
|
||||
std::string operator()(const testing::TestParamInfo<ParamType>& info) const {
|
||||
std::string name = testing::PrintToString(info.param);
|
||||
for (auto &c : name)
|
||||
if (!('0' <= c && c <= '9') && !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') ) c = '_';
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
class KernelRtlilTest : public testing::Test {
|
||||
protected:
|
||||
KernelRtlilTest() {
|
||||
if (log_files.empty()) log_files.emplace_back(stdout);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(KernelRtlilTest, ConstAssignCompare)
|
||||
{
|
||||
|
@ -74,6 +89,83 @@ namespace RTLIL {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class WireRtlVsHdlIndexConversionTest :
|
||||
public KernelRtlilTest,
|
||||
public testing::WithParamInterface<std::tuple<bool, int, int>>
|
||||
{};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
WireRtlVsHdlIndexConversionInstance,
|
||||
WireRtlVsHdlIndexConversionTest,
|
||||
testing::Values(
|
||||
std::make_tuple(false, 0, 10),
|
||||
std::make_tuple(true, 0, 10),
|
||||
std::make_tuple(false, 4, 10),
|
||||
std::make_tuple(true, 4, 10),
|
||||
std::make_tuple(false, -4, 10),
|
||||
std::make_tuple(true, -4, 10),
|
||||
std::make_tuple(false, 0, 1),
|
||||
std::make_tuple(true, 0, 1),
|
||||
std::make_tuple(false, 4, 1),
|
||||
std::make_tuple(true, 4, 1),
|
||||
std::make_tuple(false, -4, 1),
|
||||
std::make_tuple(true, -4, 1)
|
||||
),
|
||||
SafePrintToStringParamName()
|
||||
);
|
||||
|
||||
TEST_P(WireRtlVsHdlIndexConversionTest, WireRtlVsHdlIndexConversion) {
|
||||
std::unique_ptr<Module> mod = std::make_unique<Module>();
|
||||
Wire *wire = mod->addWire(ID(test), 10);
|
||||
|
||||
auto [upto, start_offset, width] = GetParam();
|
||||
|
||||
wire->upto = upto;
|
||||
wire->start_offset = start_offset;
|
||||
wire->width = width;
|
||||
|
||||
int smallest = INT_MAX;
|
||||
int largest = INT_MIN;
|
||||
|
||||
for (int i = 0; i < wire->width; i++) {
|
||||
int j = wire->to_hdl_index(i);
|
||||
smallest = std::min(smallest, j);
|
||||
largest = std::max(largest, j);
|
||||
EXPECT_EQ(
|
||||
std::make_pair(wire->from_hdl_index(j), j),
|
||||
std::make_pair(i, wire->to_hdl_index(i))
|
||||
);
|
||||
}
|
||||
|
||||
EXPECT_EQ(smallest, start_offset);
|
||||
EXPECT_EQ(largest, start_offset + wire->width - 1);
|
||||
|
||||
for (int i = 1; i < wire->width; i++) {
|
||||
EXPECT_EQ(
|
||||
wire->to_hdl_index(i) - wire->to_hdl_index(i - 1),
|
||||
upto ? -1 : 1
|
||||
);
|
||||
}
|
||||
|
||||
for (int j = smallest; j < largest; j++) {
|
||||
int i = wire->from_hdl_index(j);
|
||||
EXPECT_EQ(
|
||||
std::make_pair(wire->from_hdl_index(j), j),
|
||||
std::make_pair(i, wire->to_hdl_index(i))
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = -10; i < 0; i++)
|
||||
EXPECT_EQ(wire->to_hdl_index(i), INT_MIN);
|
||||
for (int i = wire->width; i < wire->width + 10; i++)
|
||||
EXPECT_EQ(wire->to_hdl_index(i), INT_MIN);
|
||||
for (int j = smallest - 10; j < smallest; j++)
|
||||
EXPECT_EQ(wire->from_hdl_index(j), INT_MIN);
|
||||
for (int j = largest + 1; j < largest + 11; j++)
|
||||
EXPECT_EQ(wire->from_hdl_index(j), INT_MIN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
121
tests/various/abstract_init.ys
Normal file
121
tests/various/abstract_init.ys
Normal file
|
@ -0,0 +1,121 @@
|
|||
design -reset
|
||||
read_verilog <<EOT
|
||||
module foo (CLK, Q, QQQ);
|
||||
input CLK;
|
||||
output reg QQQ;
|
||||
output reg Q = 1'b1;
|
||||
assign QQQ = Q;
|
||||
always @(posedge CLK)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
select -assert-count 1 w:Q a:init %i
|
||||
abstract -init w:QQQ
|
||||
check -assert
|
||||
select -assert-count 0 w:Q a:init %i
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module foo (CLK, Q, QQQ);
|
||||
input CLK;
|
||||
output reg QQQ;
|
||||
output reg [1:0] Q = 1'b1;
|
||||
assign QQQ = Q;
|
||||
always @(posedge CLK)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
select -assert-count 1 w:Q a:init=2'b01 %i
|
||||
abstract -init w:QQQ
|
||||
check -assert
|
||||
select -assert-count 1 w:Q a:init=2'b0x %i
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module foo (CLK, Q);
|
||||
input CLK;
|
||||
// downto
|
||||
output reg [1:0] Q = 1'b1;
|
||||
always @(posedge CLK)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
design -save basic
|
||||
select -assert-count 1 w:Q a:init=2'b01 %i
|
||||
abstract -init -slice 0 w:Q
|
||||
check -assert
|
||||
select -assert-count 1 w:Q a:init=2'b0x %i
|
||||
design -load basic
|
||||
select -assert-count 1 w:Q a:init=2'b01 %i
|
||||
abstract -init -slice 0:1 w:Q
|
||||
check -assert
|
||||
select -assert-count 0 w:Q a:init %i
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module foo (CLK, Q);
|
||||
input CLK;
|
||||
// downto
|
||||
output reg [1:0] Q = 1'b1;
|
||||
always @(posedge CLK)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
select -assert-count 1 w:Q a:init=2'b01 %i
|
||||
abstract -init -rtlilslice 0 w:Q
|
||||
check -assert
|
||||
select -assert-count 1 w:Q a:init=2'b0x %i
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module foo (CLK, Q);
|
||||
input CLK;
|
||||
// upto
|
||||
output reg [0:1] Q = 1'b1;
|
||||
always @(posedge CLK)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
select -assert-count 1 w:Q a:init=2'b01 %i
|
||||
abstract -init -slice 0 w:Q
|
||||
check -assert
|
||||
select -assert-count 1 w:Q a:init=2'bx1 %i
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module foo (CLK, Q);
|
||||
input CLK;
|
||||
// upto
|
||||
output reg [0:1] Q = 1'b1;
|
||||
always @(posedge CLK)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
select -assert-count 1 w:Q a:init=2'b01 %i
|
||||
abstract -init -rtlilslice 0 w:Q
|
||||
check -assert
|
||||
select -assert-count 1 w:Q a:init=2'b0x %i
|
178
tests/various/abstract_state.ys
Normal file
178
tests/various/abstract_state.ys
Normal file
|
@ -0,0 +1,178 @@
|
|||
read_verilog <<EOT
|
||||
|
||||
module half_clock (CLK, Q, magic);
|
||||
input CLK;
|
||||
output reg Q;
|
||||
input magic;
|
||||
always @(posedge CLK)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
|
||||
EOT
|
||||
proc
|
||||
design -save half_clock
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# An empty selection causes no change
|
||||
select -none
|
||||
|
||||
logger -expect log "Abstracted 0 stateful cells" 1
|
||||
abstract -state -enablen magic
|
||||
logger -check-expected
|
||||
|
||||
logger -expect log "Abstracted 0 init bits" 1
|
||||
abstract -init
|
||||
logger -check-expected
|
||||
|
||||
logger -expect log "Abstracted 0 driver ports" 1
|
||||
abstract -value -enablen magic
|
||||
logger -check-expected
|
||||
|
||||
select -clear
|
||||
# -----------------------------------------------------------------------------
|
||||
design -load half_clock
|
||||
# Basic -state test
|
||||
abstract -state -enablen magic
|
||||
check -assert
|
||||
# Connections to dff D input port
|
||||
select -set conn_to_d t:$dff %x:+[D] t:$dff %d
|
||||
# The D input port is fed with a mux
|
||||
select -set mux @conn_to_d %ci t:$mux %i
|
||||
select -assert-count 1 @mux
|
||||
# The S input port is fed with the magic wire
|
||||
select -assert-count 1 @mux %x:+[S] w:magic %i
|
||||
# The A input port is fed with an anyseq
|
||||
select -assert-count 1 @mux %x:+[A] %ci t:$anyseq %i
|
||||
# The B input port is fed with the negated Q
|
||||
select -set not @mux %x:+[B] %ci t:$not %i
|
||||
select -assert-count 1 @not %x:+[A] o:Q %i
|
||||
|
||||
design -load half_clock
|
||||
# Same thing, inverted polarity
|
||||
abstract -state -enable magic
|
||||
check -assert
|
||||
select -set conn_to_d t:$dff %x:+[D] t:$dff %d
|
||||
select -set mux @conn_to_d %ci t:$mux %i
|
||||
select -assert-count 1 @mux
|
||||
select -assert-count 1 @mux %x:+[S] w:magic %i
|
||||
# so we get swapped A and B
|
||||
select -assert-count 1 @mux %x:+[B] %ci t:$anyseq %i
|
||||
select -set not @mux %x:+[A] %ci t:$not %i
|
||||
select -assert-count 1 @not %x:+[A] o:Q %i
|
||||
# -----------------------------------------------------------------------------
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module wide_flop_no_q (CLK, DDD, QQQ, magic);
|
||||
input CLK;
|
||||
input [2:0] DDD;
|
||||
output reg [2:0] QQQ;
|
||||
input magic;
|
||||
always @(posedge CLK)
|
||||
QQQ <= DDD;
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
dump
|
||||
abstract -state -enablen magic -slice 0 w:QQQ
|
||||
check -assert
|
||||
# Connections to dff D input port
|
||||
select -set conn_to_d t:$dff %x:+[D] t:$dff %d
|
||||
# The D input port is partially fed with a mux
|
||||
select -set mux @conn_to_d %ci t:$mux %i
|
||||
select -assert-count 1 @mux
|
||||
# and also the DDD input
|
||||
select -assert-count 1 @conn_to_d w:DDD %i
|
||||
# The S input port is fed with the magic wire
|
||||
select -assert-count 1 @mux %x:+[S] w:magic %i
|
||||
# The A input port is fed with an anyseq
|
||||
select -assert-count 1 @mux %x:+[A] %ci t:$anyseq %i
|
||||
# The B input port is fed with DDD
|
||||
select -assert-count 1 @mux %x:+[B] %ci w:DDD %i
|
||||
# -----------------------------------------------------------------------------
|
||||
# Selecting wire Q connected to bit 0 of QQQ is the same as specifying
|
||||
# QQQ with the -slice 0 argument
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module wide_flop (CLK, DDD, QQQ, Q, magic);
|
||||
input CLK;
|
||||
input [2:0] DDD;
|
||||
output reg [2:0] QQQ;
|
||||
output reg Q;
|
||||
input magic;
|
||||
always @(posedge CLK)
|
||||
QQQ <= DDD;
|
||||
assign Q = QQQ[0];
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
design -save wide_flop
|
||||
# Test that abstracting an output slice muxes an input slice
|
||||
abstract -state -enablen magic w:Q
|
||||
check -assert
|
||||
# Same testing as previous case
|
||||
select -set conn_to_d t:$dff %x:+[D] t:$dff %d
|
||||
select -set mux @conn_to_d %ci t:$mux %i
|
||||
select -assert-count 1 @mux
|
||||
select -assert-count 1 @conn_to_d w:DDD %i
|
||||
select -assert-count 1 @mux %x:+[S] w:magic %i
|
||||
select -assert-count 1 @mux %x:+[A] %ci t:$anyseq %i
|
||||
select -assert-count 1 @mux %x:+[B] %ci w:DDD %i
|
||||
# -----------------------------------------------------------------------------
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module half_clock_en (CLK, E, Q, magic);
|
||||
input CLK;
|
||||
input E;
|
||||
output reg Q;
|
||||
input magic;
|
||||
always @(posedge CLK)
|
||||
if (E)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
design -save half_clock_en
|
||||
# Test that abstracting a $dffe unmaps the enable
|
||||
select -assert-count 1 t:$dffe
|
||||
abstract -state -enablen magic
|
||||
check -assert
|
||||
select -assert-count 0 t:$dffe
|
||||
select -assert-count 1 t:$dff
|
||||
# -----------------------------------------------------------------------------
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module top (CLK, E, Q, Q_EN);
|
||||
input CLK;
|
||||
input E;
|
||||
output reg Q;
|
||||
output reg Q_EN;
|
||||
half_clock uut (CLK, Q, 1'b0);
|
||||
half_clock_en uut_en (CLK, E, Q_EN, 1'b0);
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
design -import half_clock
|
||||
design -import half_clock_en
|
||||
hierarchy -check -top top
|
||||
# Test when the abstraction is disabled (enable is inactive),
|
||||
# the equivalence is preserved
|
||||
rename top top_gold
|
||||
design -save gold
|
||||
abstract -state -enable magic half_clock half_clock_en
|
||||
flatten
|
||||
rename top_gold top_gate
|
||||
design -save gate
|
||||
design -load gold
|
||||
flatten
|
||||
design -import gate -as top_gate
|
||||
|
||||
equiv_make top_gold top_gate equiv
|
||||
equiv_induct equiv
|
||||
equiv_status -assert equiv
|
||||
# The reader may verify that this model checking is functional
|
||||
# by changing -enable to -enablen in the abstract pass invocation above
|
||||
# -----------------------------------------------------------------------------
|
95
tests/various/abstract_value.ys
Normal file
95
tests/various/abstract_value.ys
Normal file
|
@ -0,0 +1,95 @@
|
|||
read_verilog <<EOT
|
||||
module split_output (A, B, Y, magic);
|
||||
input [1:0] A;
|
||||
input [1:0] B;
|
||||
output [1:0] Y;
|
||||
input magic;
|
||||
wire W;
|
||||
assign Y = A + B;
|
||||
assign W = Y[0]; // <--- look here
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
design -save split_output
|
||||
# Basic -value test
|
||||
abstract -value -enable magic w:W
|
||||
check -assert
|
||||
# Connections to $add Y output port
|
||||
select -set conn_to_y t:$add %x:+[Y] t:$add %d
|
||||
# The $add Y output port feeds partially into a mux
|
||||
select -set mux @conn_to_y %ci t:$mux %i
|
||||
select -assert-count 1 @mux
|
||||
# and also the Y module output
|
||||
select -assert-count 1 @conn_to_y %a o:Y %i
|
||||
# The S input port is fed with the magic wire
|
||||
select -assert-count 1 @mux %x:+[S] w:magic %i
|
||||
# The B input port is fed with an anyseq
|
||||
select -assert-count 1 @mux %x:+[B] %ci t:$anyseq %i
|
||||
# The Y output port feeds into the Y module output
|
||||
select -assert-count 1 @mux %x:+[Y] %co o:Y %i
|
||||
# -----------------------------------------------------------------------------
|
||||
# Same thing, but we use -slice instead of wire W
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module split_output_no_w (A, B, Y, magic);
|
||||
input [1:0] A;
|
||||
input [1:0] B;
|
||||
output [1:0] Y;
|
||||
input magic;
|
||||
assign Y = A + B;
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
# Same test as the previous case
|
||||
abstract -value -enable magic -slice 0 w:Y
|
||||
check -assert
|
||||
select -set conn_to_y t:$add %x:+[Y] t:$add %d
|
||||
select -set mux @conn_to_y %ci t:$mux %i
|
||||
select -assert-count 1 @mux
|
||||
select -assert-count 1 @conn_to_y %a o:Y %i
|
||||
select -assert-count 1 @mux %x:+[S] w:magic %i
|
||||
select -assert-count 1 @mux %x:+[B] %ci t:$anyseq %i
|
||||
select -assert-count 1 @mux %x:+[Y] %co o:Y %i
|
||||
# -----------------------------------------------------------------------------
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module split_input (A, B, Y, magic);
|
||||
input [1:0] A;
|
||||
input [1:0] B;
|
||||
output [1:0] Y;
|
||||
input magic;
|
||||
wire W;
|
||||
assign Y = A + B;
|
||||
assign W = A[0]; // <--- look here
|
||||
endmodule
|
||||
EOT
|
||||
proc
|
||||
design -save split_input
|
||||
# The mux goes on an input this time
|
||||
abstract -value -enable magic w:W
|
||||
check -assert
|
||||
# Connections to add A input port
|
||||
select -set conn_to_a t:$add %x:+[A] t:$add %d
|
||||
# The B input port is partially fed with a mux
|
||||
select -set mux @conn_to_a %ci t:$mux %i
|
||||
select -assert-count 1 @mux
|
||||
# and also the A input
|
||||
select -assert-count 1 @conn_to_a %a w:A %i
|
||||
# The S input port is fed with the magic wire
|
||||
select -assert-count 1 @mux %x:+[S] w:magic %i
|
||||
# The A input port is fed with the module input A
|
||||
select -assert-count 1 @mux %x:+[A] %ci i:A %i
|
||||
# The B input port is fed with an anyseq
|
||||
select -assert-count 1 @mux %x:+[B] %ci t:$anyseq %i
|
||||
# -----------------------------------------------------------------------------
|
||||
# All wires selected, excluding magic -> muxes on inputs and outputs
|
||||
design -load split_output
|
||||
select -assert-count 0 t:$mux
|
||||
abstract -value -enable magic w:* w:magic %d
|
||||
select -assert-count 3 t:$mux
|
||||
# All cells selected -> muxes on outputs only
|
||||
design -load split_output
|
||||
select -assert-count 0 t:$mux
|
||||
abstract -value -enable magic t:*
|
||||
select -assert-count 1 t:$mux
|
||||
# -----------------------------------------------------------------------------
|
Loading…
Add table
Add a link
Reference in a new issue