mirror of
https://github.com/YosysHQ/yosys
synced 2025-11-04 21:39:14 +00:00
hierarchy.cc: Raise error on positional interface
Add test to check that it does error.
This commit is contained in:
parent
bbceaa6b5e
commit
7bb0a1913e
3 changed files with 82 additions and 21 deletions
|
|
@ -156,6 +156,21 @@ std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) {
|
||||||
return basicType;
|
return basicType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to read an IdString as a numbered connection name ("$123" or similar),
|
||||||
|
// writing the result to dst. If the string isn't of the right format, ignore
|
||||||
|
// dst and return false.
|
||||||
|
bool read_id_num(RTLIL::IdString str, int *dst)
|
||||||
|
{
|
||||||
|
log_assert(dst);
|
||||||
|
|
||||||
|
const char *c_str = str.c_str();
|
||||||
|
if (c_str[0] != '$' || !('0' <= c_str[1] && c_str[1] <= '9'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*dst = atoi(c_str + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// A helper struct for expanding a module's interface connections in expand_module
|
// A helper struct for expanding a module's interface connections in expand_module
|
||||||
struct IFExpander
|
struct IFExpander
|
||||||
{
|
{
|
||||||
|
|
@ -283,15 +298,42 @@ struct IFExpander
|
||||||
RTLIL::IdString conn_name,
|
RTLIL::IdString conn_name,
|
||||||
const RTLIL::SigSpec &conn_signals)
|
const RTLIL::SigSpec &conn_signals)
|
||||||
{
|
{
|
||||||
// Check if the connection is present as an interface in the sub-module's port list
|
// Does the connection look like an interface
|
||||||
const RTLIL::Wire *wire = submodule.wire(conn_name);
|
const auto &bits = conn_signals;
|
||||||
if (!wire || !wire->get_bool_attribute(ID::is_interface))
|
if (
|
||||||
|
bits.size() != 1 ||
|
||||||
|
!bits[0].wire->get_bool_attribute(ID::is_interface) ||
|
||||||
|
conn_signals[0].wire->name.str().find("$dummywireforinterface") != 0
|
||||||
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Check if the connection is present as an interface in the sub-module's port list
|
||||||
|
int id;
|
||||||
|
if (read_id_num(conn_name, &id)) {
|
||||||
|
/* Interface expansion is incompatible with positional arguments
|
||||||
|
* during expansion, the port list gets each interface signal
|
||||||
|
* inserted after the interface itself which means that the argument
|
||||||
|
* positions in the parent module no longer match.
|
||||||
|
*
|
||||||
|
* Supporting this would require expanding the interfaces in the
|
||||||
|
* parent module, renumbering the arguments to match, and then
|
||||||
|
* iterating over the ports list to find the matching interface
|
||||||
|
* (refactoring on_interface to accept different conn_names on the
|
||||||
|
* parent and child).
|
||||||
|
*/
|
||||||
|
log_error("Unable to connect `%s' to submodule `%s' with positional interface argument `%s'!\n",
|
||||||
|
module.name,
|
||||||
|
submodule.name,
|
||||||
|
conn_signals[0].wire->name.str().substr(23)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Lookup connection by name
|
||||||
|
const RTLIL::Wire *wire = submodule.wire(conn_name);
|
||||||
|
if (!wire || !wire->get_bool_attribute(ID::is_interface))
|
||||||
|
return;
|
||||||
|
}
|
||||||
// If the connection looks like an interface, handle it.
|
// If the connection looks like an interface, handle it.
|
||||||
const auto &bits = conn_signals;
|
on_interface(submodule, conn_name, conn_signals);
|
||||||
if (bits.size() == 1 && bits[0].wire->get_bool_attribute(ID::is_interface))
|
|
||||||
on_interface(submodule, conn_name, conn_signals);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over the connections in a cell, tracking any interface
|
// Iterate over the connections in a cell, tracking any interface
|
||||||
|
|
@ -376,21 +418,6 @@ RTLIL::Module *get_module(RTLIL::Design &design,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to read an IdString as a numbered connection name ("$123" or similar),
|
|
||||||
// writing the result to dst. If the string isn't of the right format, ignore
|
|
||||||
// dst and return false.
|
|
||||||
bool read_id_num(RTLIL::IdString str, int *dst)
|
|
||||||
{
|
|
||||||
log_assert(dst);
|
|
||||||
|
|
||||||
const char *c_str = str.c_str();
|
|
||||||
if (c_str[0] != '$' || !('0' <= c_str[1] && c_str[1] <= '9'))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*dst = atoi(c_str + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the connections on the cell match those that are defined
|
// Check that the connections on the cell match those that are defined
|
||||||
// on the type: each named connection should match the name of a port
|
// on the type: each named connection should match the name of a port
|
||||||
// and each positional connection should have an index smaller than
|
// and each positional connection should have an index smaller than
|
||||||
|
|
|
||||||
33
tests/svinterfaces/positional_args.ys
Normal file
33
tests/svinterfaces/positional_args.ys
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
read_verilog -sv << EOF
|
||||||
|
interface simple_if;
|
||||||
|
logic receiver;
|
||||||
|
logic driver;
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
module driver_mod(simple_if intf, input in);
|
||||||
|
assign intf.driver = in;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module receiver_mod(simple_if intf);
|
||||||
|
assign intf.receiver = intf.driver;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module top(
|
||||||
|
input logic [1:0] inputs,
|
||||||
|
output logic [1:0] outputs
|
||||||
|
);
|
||||||
|
simple_if intf0();
|
||||||
|
simple_if intf1();
|
||||||
|
|
||||||
|
driver_mod d0(intf0, inputs[0]);
|
||||||
|
driver_mod d1(intf1, inputs[1]);
|
||||||
|
|
||||||
|
receiver_mod r0(intf0);
|
||||||
|
receiver_mod r1(intf1);
|
||||||
|
|
||||||
|
assign outputs = {intf0.receiver, intf1.receiver};
|
||||||
|
endmodule
|
||||||
|
EOF
|
||||||
|
|
||||||
|
logger -expect error "Unable to connect.* with positional interface" 1
|
||||||
|
hierarchy -top top
|
||||||
1
tests/svinterfaces/run-test.sh
Executable file → Normal file
1
tests/svinterfaces/run-test.sh
Executable file → Normal file
|
|
@ -5,3 +5,4 @@
|
||||||
|
|
||||||
./run_simple.sh load_and_derive
|
./run_simple.sh load_and_derive
|
||||||
./run_simple.sh resolve_types
|
./run_simple.sh resolve_types
|
||||||
|
./run_simple.sh positional_args
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue