Merge pull request #4815 from YosysHQ/verific_bounds_fix

Verific frontend: fix `top_bound`/`bottom_bound` attributes
This commit is contained in:
N. Engelhardt 2024-12-12 12:59:55 +01:00 committed by GitHub
commit f384eac28b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 331 additions and 25 deletions

View File

@ -407,7 +407,7 @@ static const std::string verific_unescape(const char *value)
}
#endif
void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj, Netlist *nl)
void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj, Netlist *nl, int wire_width_hint)
{
if (!obj)
return;
@ -433,10 +433,18 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
auto type_range = nl->GetTypeRange(obj->Name());
if (!type_range)
return;
if (type_range->IsTypeScalar()) {
if (nl->IsFromVhdl() && type_range->IsTypeScalar()) {
const long long bottom_bound = type_range->GetScalarRangeLeftBound();
const long long top_bound = type_range->GetScalarRangeRightBound();
const unsigned bit_width = type_range->NumElements();
int bit_width = type_range->LeftRangeBound()+1;
if (bit_width <= 0) { // VHDL null range
if (wire_width_hint >= 0)
bit_width = wire_width_hint;
else
bit_width = 64; //fallback, currently largest integer width that verific will allow (in vhdl2019 mode)
} else {
if (wire_width_hint >= 0) log_assert(bit_width == wire_width_hint);
}
RTLIL::Const bottom_const(bottom_bound, bit_width);
RTLIL::Const top_const(top_bound, bit_width);
if (bottom_bound < 0 || top_bound < 0) {
@ -1499,7 +1507,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
log(" importing port %s.\n", port->Name());
RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(port->Name()));
import_attributes(wire->attributes, port, nl);
import_attributes(wire->attributes, port, nl, 1);
wire->port_id = nl->IndexOf(port) + 1;
@ -1527,11 +1535,11 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
RTLIL::Wire *wire = module->addWire(RTLIL::escape_id(portbus->Name()), portbus->Size());
wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex());
wire->upto = portbus->IsUp();
import_attributes(wire->attributes, portbus, nl);
import_attributes(wire->attributes, portbus, nl, portbus->Size());
SetIter si ;
Port *port ;
FOREACH_PORT_OF_PORTBUS(portbus, si, port) {
import_attributes(wire->attributes, port->GetNet(), nl);
import_attributes(wire->attributes, port->GetNet(), nl, portbus->Size());
break;
}
bool portbus_input = portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN;
@ -1693,7 +1701,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
log(" importing net %s as %s.\n", net->Name(), log_id(wire_name));
RTLIL::Wire *wire = module->addWire(wire_name);
import_attributes(wire->attributes, net, nl);
import_attributes(wire->attributes, net, nl, 1);
net_map[net] = wire;
}
@ -1722,10 +1730,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
MapIter mibus;
FOREACH_NET_OF_NETBUS(netbus, mibus, net) {
if (net)
import_attributes(wire->attributes, net, nl);
import_attributes(wire->attributes, net, nl, netbus->Size());
break;
}
import_attributes(wire->attributes, netbus, nl);
import_attributes(wire->attributes, netbus, nl, netbus->Size());
RTLIL::Const initval = Const(State::Sx, GetSize(wire));
bool initval_valid = false;

View File

@ -81,7 +81,7 @@ struct VerificImporter
RTLIL::SigBit net_map_at(Verific::Net *net);
RTLIL::IdString new_verific_id(Verific::DesignObj *obj);
void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, Verific::DesignObj *obj, Verific::Netlist *nl = nullptr);
void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, Verific::DesignObj *obj, Verific::Netlist *nl = nullptr, int wire_width_hint = -1);
RTLIL::SigBit netToSigBit(Verific::Net *net);
RTLIL::SigSpec operatorInput(Verific::Instance *inst);

45
tests/verific/bounds.sv Normal file
View File

@ -0,0 +1,45 @@
typedef enum {IDLE, RUN, STOP} state_t;
typedef struct {
logic [7:0] field1;
int field2;
} my_struct_t;
// Submodule to handle the interface ports
module submodule (
my_ifc i_ifc,
my_ifc o_ifc
);
// Connect the interface signals
assign o_ifc.data = i_ifc.data;
endmodule
module test (
input i_a,
output o_a,
input [0:0] i_b,
output [0:0] o_b,
input [3:0] i_c,
output [3:0] o_c,
input logic i_d,
output logic o_d,
input bit [7:0] i_e,
output bit [7:0] o_e,
input int i_f,
output int o_f,
input state_t i_h,
output state_t o_h,
input my_struct_t i_i,
output my_struct_t o_i
);
assign o_a = i_a;
assign o_b = i_b;
assign o_c = i_c;
assign o_d = i_d;
assign o_e = i_e;
assign o_f = i_f;
assign o_h = i_h;
assign o_i = i_i;
endmodule

View File

@ -2,17 +2,108 @@ library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity work is
entity test is
Port (
a : in INTEGER range -5 to 10;
b : out INTEGER range -6 to 11
);
end entity work;
-- BIT type
bit_in : in BIT;
bit_out : out BIT;
architecture Behavioral of work is
-- BIT_VECTOR type
bit_vector_in : in BIT_VECTOR(3 downto 0);
bit_vector_out : out BIT_VECTOR(3 downto 0);
-- BIT_VECTOR type with to index
bit_vector_in_to : in BIT_VECTOR(0 to 3);
bit_vector_out_to : out BIT_VECTOR(0 to 3);
-- STD_ULOGIC type
std_ulogic_in : in STD_ULOGIC;
std_ulogic_out : out STD_ULOGIC;
-- STD_ULOGIC_VECTOR type
std_ulogic_vector_in : in STD_ULOGIC_VECTOR(3 downto 0);
std_ulogic_vector_out : out STD_ULOGIC_VECTOR(3 downto 0);
-- STD_ULOGIC_VECTOR type with to index
std_ulogic_vector_in_to : in STD_ULOGIC_VECTOR(0 to 3);
std_ulogic_vector_out_to : out STD_ULOGIC_VECTOR(0 to 3);
-- STD_LOGIC type
std_logic_in : in STD_LOGIC;
std_logic_out : out STD_LOGIC;
-- STD_LOGIC_VECTOR type
std_logic_vector_in : in STD_LOGIC_VECTOR(3 downto 0);
std_logic_vector_out : out STD_LOGIC_VECTOR(3 downto 0);
-- STD_LOGIC_VECTOR type with to index
std_logic_vector_in_to : in STD_LOGIC_VECTOR(0 to 3);
std_logic_vector_out_to : out STD_LOGIC_VECTOR(0 to 3);
-- SIGNED type
signed_in : in SIGNED(3 downto 0);
signed_out : out SIGNED(3 downto 0);
-- SIGNED type with to index
signed_in_to : in SIGNED(0 to 3);
signed_out_to : out SIGNED(0 to 3);
-- UNSIGNED type
unsigned_in : in UNSIGNED(3 downto 0);
unsigned_out : out UNSIGNED(3 downto 0);
-- UNSIGNED type with to index
unsigned_in_to : in UNSIGNED(0 to 3);
unsigned_out_to : out UNSIGNED(0 to 3);
-- INTEGER type without range
integer_in : in INTEGER;
integer_out : out INTEGER;
-- INTEGER type with range
integer_with_range_in : in INTEGER range -5 to 10;
integer_with_range_out : out INTEGER range -6 to 10;
-- INTEGER type with single value range
integer_single_value_in : in INTEGER range 5 to 5;
integer_single_value_out : out INTEGER range 5 to 5;
-- INTEGER type with null range
integer_null_range_in : in INTEGER range 7 to -1;
integer_null_range_out : out INTEGER range 0 to -1;
-- NATURAL type
natural_in : in NATURAL;
natural_out : out NATURAL;
-- POSITIVE type
positive_in : in POSITIVE;
positive_out : out POSITIVE
);
end entity test;
architecture Behavioral of test is
signal integer_with_range : INTEGER range -1 to 100;
begin
process(a)
begin
b <= a;
end process;
bit_out <= bit_in;
bit_vector_out <= bit_vector_in;
bit_vector_out_to <= bit_vector_in_to;
std_ulogic_out <= std_ulogic_in;
std_ulogic_vector_out <= std_ulogic_vector_in;
std_ulogic_vector_out_to <= std_ulogic_vector_in_to;
std_logic_out <= std_logic_in;
std_logic_vector_out <= std_logic_vector_in;
std_logic_vector_out_to <= std_logic_vector_in_to;
signed_out <= signed_in;
signed_out_to <= signed_in_to;
unsigned_out <= unsigned_in;
unsigned_out_to <= unsigned_in_to;
integer_with_range_out <= integer_with_range_in;
integer_out <= integer_in;
integer_single_value_out <= integer_single_value_in;
integer_null_range_out <= integer_null_range_in;
natural_out <= natural_in;
positive_out <= positive_in;
integer_with_range <= 42;
end architecture Behavioral;

View File

@ -1,6 +1,168 @@
read -vhdl bounds.vhd
verific -import work
select -assert-count 1 a:bottom_bound=5'bs11011
select -assert-count 1 a:top_bound=5'bs01010
select -assert-count 1 a:bottom_bound=5'bs11010
select -assert-count 1 a:top_bound=5'bs01011
hierarchy -top test
# bit: not a scalar type
select -assert-count 0 w:bit_in a:bottom_bound %i
select -assert-count 0 w:bit_in a:top_bound %i
select -assert-count 0 w:bit_out a:bottom_bound %i
select -assert-count 0 w:bit_out a:top_bound %i
# bit_vector: not a scalar type
select -assert-count 0 w:bit_vector_in a:bottom_bound %i
select -assert-count 0 w:bit_vector_in a:top_bound %i
select -assert-count 0 w:bit_vector_out a:bottom_bound %i
select -assert-count 0 w:bit_vector_out a:top_bound %i
# bit_vector with to index: not a scalar type
select -assert-count 0 w:bit_vector_in_to a:bottom_bound %i
select -assert-count 0 w:bit_vector_in_to a:top_bound %i
select -assert-count 0 w:bit_vector_out_to a:bottom_bound %i
select -assert-count 0 w:bit_vector_out_to a:top_bound %i
# std_ulogic: not a scalar type
select -assert-count 0 w:std_ulogic_in a:bottom_bound %i
select -assert-count 0 w:std_ulogic_in a:top_bound %i
select -assert-count 0 w:std_ulogic_out a:bottom_bound %i
select -assert-count 0 w:std_ulogic_out a:top_bound %i
# std_ulogic_vector: not a scalar type
select -assert-count 0 w:std_ulogic_vector_in a:bottom_bound %i
select -assert-count 0 w:std_ulogic_vector_in a:top_bound %i
select -assert-count 0 w:std_ulogic_vector_out a:bottom_bound %i
select -assert-count 0 w:std_ulogic_vector_out a:top_bound %i
# std_ulogic_vector with to index: not a scalar type
select -assert-count 0 w:std_ulogic_vector_in_to a:bottom_bound %i
select -assert-count 0 w:std_ulogic_vector_in_to a:top_bound %i
select -assert-count 0 w:std_ulogic_vector_out_to a:bottom_bound %i
select -assert-count 0 w:std_ulogic_vector_out_to a:top_bound %i
# std_logic: not a scalar type
select -assert-count 0 w:std_logic_in a:bottom_bound %i
select -assert-count 0 w:std_logic_in a:top_bound %i
select -assert-count 0 w:std_logic_out a:bottom_bound %i
select -assert-count 0 w:std_logic_out a:top_bound %i
# std_logic_vector: not a scalar type
select -assert-count 0 w:std_logic_vector_in a:bottom_bound %i
select -assert-count 0 w:std_logic_vector_in a:top_bound %i
select -assert-count 0 w:std_logic_vector_out a:bottom_bound %i
select -assert-count 0 w:std_logic_vector_out a:top_bound %i
# std_logic_vector with to index: not a scalar type
select -assert-count 0 w:std_logic_vector_in_to a:bottom_bound %i
select -assert-count 0 w:std_logic_vector_in_to a:top_bound %i
select -assert-count 0 w:std_logic_vector_out_to a:bottom_bound %i
select -assert-count 0 w:std_logic_vector_out_to a:top_bound %i
# signed: not a scalar type
select -assert-count 0 w:signed_in a:bottom_bound %i
select -assert-count 0 w:signed_in a:top_bound %i
select -assert-count 0 w:signed_out a:bottom_bound %i
select -assert-count 0 w:signed_out a:top_bound %i
# signed with to index: not a scalar type
select -assert-count 0 w:signed_in_to a:bottom_bound %i
select -assert-count 0 w:signed_in_to a:top_bound %i
select -assert-count 0 w:signed_out_to a:bottom_bound %i
select -assert-count 0 w:signed_out_to a:top_bound %i
# unsigned: not a scalar type
select -assert-count 0 w:unsigned_in a:bottom_bound %i
select -assert-count 0 w:unsigned_in a:top_bound %i
select -assert-count 0 w:unsigned_out a:bottom_bound %i
select -assert-count 0 w:unsigned_out a:top_bound %i
# unsigned with to index: not a scalar type
select -assert-count 0 w:unsigned_in_to a:bottom_bound %i
select -assert-count 0 w:unsigned_in_to a:top_bound %i
select -assert-count 0 w:unsigned_out_to a:bottom_bound %i
select -assert-count 0 w:unsigned_out_to a:top_bound %i
# integer: scalar type
select -assert-count 1 w:integer_in a:bottom_bound=32'b10000000000000000000000000000000 %i
select -assert-count 1 w:integer_in a:top_bound=32'b01111111111111111111111111111111 %i
select -assert-count 1 w:integer_out a:bottom_bound=32'b10000000000000000000000000000000 %i
select -assert-count 1 w:integer_out a:top_bound=32'b01111111111111111111111111111111 %i
# integer with range: scalar type
select -assert-count 1 w:integer_with_range_in a:bottom_bound=5'bs11011 %i
select -assert-count 1 w:integer_with_range_in a:top_bound=5'bs01010 %i
select -assert-count 1 w:integer_with_range_out a:bottom_bound=5'bs11010 %i
select -assert-count 1 w:integer_with_range_out a:top_bound=5'bs01010 %i
# integer with single value range: scalar type
select -assert-count 1 w:integer_single_value_in a:bottom_bound=3'bs101 %i
select -assert-count 1 w:integer_single_value_in a:top_bound=3'bs101 %i
select -assert-count 1 w:integer_single_value_out a:bottom_bound=3'bs101 %i
select -assert-count 1 w:integer_single_value_out a:top_bound=3'bs101 %i
# integer with null range: scalar type
select -assert-count 1 w:integer_null_range_in a:bottom_bound=4'bs0111 %i
select -assert-count 1 w:integer_null_range_in a:top_bound=4'bs1111 %i
select -assert-count 1 w:integer_null_range_out a:bottom_bound=1'bs0 %i
select -assert-count 1 w:integer_null_range_out a:top_bound=1'bs1 %i
# natural: scalar type
select -assert-count 1 w:natural_in a:bottom_bound=31'b0000000000000000000000000000000 %i
select -assert-count 1 w:natural_in a:top_bound=31'b1111111111111111111111111111111 %i
select -assert-count 1 w:natural_out a:bottom_bound=31'b0000000000000000000000000000000 %i
select -assert-count 1 w:natural_out a:top_bound=31'b1111111111111111111111111111111 %i
# positive: scalar type
select -assert-count 1 w:positive_in a:bottom_bound=31'b0000000000000000000000000000001 %i
select -assert-count 1 w:positive_in a:top_bound=31'b1111111111111111111111111111111 %i
select -assert-count 1 w:positive_out a:bottom_bound=31'b0000000000000000000000000000001 %i
select -assert-count 1 w:positive_out a:top_bound=31'b1111111111111111111111111111111 %i
design -reset
read -vhdl2019 bounds.vhd
hierarchy -top test
## integer size changed in VHDL 2019
# integer: scalar type
select -assert-count 1 w:integer_in a:bottom_bound=64'b1000000000000000000000000000000000000000000000000000000000000000 %i
select -assert-count 1 w:integer_in a:top_bound=64'b0111111111111111111111111111111111111111111111111111111111111111 %i
select -assert-count 1 w:integer_out a:bottom_bound=64'b1000000000000000000000000000000000000000000000000000000000000000 %i
select -assert-count 1 w:integer_out a:top_bound=64'b0111111111111111111111111111111111111111111111111111111111111111 %i
# natural: scalar type
select -assert-count 1 w:natural_in a:bottom_bound=63'b000000000000000000000000000000000000000000000000000000000000000 %i
select -assert-count 1 w:natural_in a:top_bound=63'b111111111111111111111111111111111111111111111111111111111111111 %i
select -assert-count 1 w:natural_out a:bottom_bound=63'b000000000000000000000000000000000000000000000000000000000000000 %i
select -assert-count 1 w:natural_out a:top_bound=63'b111111111111111111111111111111111111111111111111111111111111111 %i
# positive: scalar type
select -assert-count 1 w:positive_in a:bottom_bound=63'b000000000000000000000000000000000000000000000000000000000000001 %i
select -assert-count 1 w:positive_in a:top_bound=63'b111111111111111111111111111111111111111111111111111111111111111 %i
select -assert-count 1 w:positive_out a:bottom_bound=63'b000000000000000000000000000000000000000000000000000000000000001 %i
select -assert-count 1 w:positive_out a:top_bound=63'b111111111111111111111111111111111111111111111111111111111111111 %i
## ranged integer sizes should be unaffected
# integer with range: scalar type
select -assert-count 1 w:integer_with_range_in a:bottom_bound=5'bs11011 %i
select -assert-count 1 w:integer_with_range_in a:top_bound=5'bs01010 %i
select -assert-count 1 w:integer_with_range_out a:bottom_bound=5'bs11010 %i
select -assert-count 1 w:integer_with_range_out a:top_bound=5'bs01010 %i
# integer with single value range: scalar type
select -assert-count 1 w:integer_single_value_in a:bottom_bound=3'bs101 %i
select -assert-count 1 w:integer_single_value_in a:top_bound=3'bs101 %i
select -assert-count 1 w:integer_single_value_out a:bottom_bound=3'bs101 %i
select -assert-count 1 w:integer_single_value_out a:top_bound=3'bs101 %i
# integer with null range: scalar type
select -assert-count 1 w:integer_null_range_in a:bottom_bound=4'bs0111 %i
select -assert-count 1 w:integer_null_range_in a:top_bound=4'bs1111 %i
select -assert-count 1 w:integer_null_range_out a:bottom_bound=1'bs0 %i
select -assert-count 1 w:integer_null_range_out a:top_bound=1'bs1 %i
design -reset
read -sv bounds.sv
hierarchy -top test
## bounds should not be generated for SV
select -assert-count none a:bottom_bound
select -assert-count none a:top_bound