3
0
Fork 0
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:
Akash Levy 2025-02-26 09:51:44 -08:00 committed by GitHub
commit 9d3b7f7474
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 1019 additions and 10 deletions

View file

@ -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

View 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

View 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
# -----------------------------------------------------------------------------

View 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
# -----------------------------------------------------------------------------