Difference between revisions of "Simple port modification"
From Verific Design Automation FAQ
(Created page with "This example converts module with struct ports into flat ports. <nowiki> from invio import * set_preference("invio_insert_ports_with_newline", 1) add_sv_file("test.sv") ana...") |
|||
Line 9: | Line 9: | ||
elaborate("top") | elaborate("top") | ||
− | # Convert | + | # Convert instance of the module with struct ports into flat ports |
− | + | mod = get_modules("child").first | |
− | for | + | for i in get_instances(mod): |
− | + | for p in i.portmaps: | |
+ | pin = p.pin | ||
+ | if pin and pin.data_type.is_named_user_type: | ||
+ | print(f'... Replacing portmap: {p.full_name}') | ||
+ | portmap = '' | ||
+ | for m in pin.data_type.members: | ||
+ | portmap = portmap + f'.{pin.base_name}_{m.base_name} ({p.connected.first.base_name}.{m.base_name})' + ', \n' | ||
+ | rt = create_raw_text_object(ref=p) | ||
+ | replace_orig_text_of_object(rt, portmap[:len(portmap)-3]) # trim off the last ', ' | ||
+ | # You will need to write out the modification and relaod to see the effect of text replacement in the parse tree. | ||
+ | |||
+ | |||
+ | # Replace the assignment with raw text | ||
+ | a = get_assigns(mod).first | ||
+ | new_assign = """assign out_bus_clk = in_bus_clk; | ||
+ | assign out_bus_rst = in_bus_rst; | ||
+ | assign out_bus_addr = in_bus_addr; | ||
+ | assign out_bus_data = in_bus_data; | ||
+ | """ | ||
+ | print(f'... Replacing assignment: {a.full_name}') | ||
+ | replace_orig_text_of_object(a, new_assign) | ||
+ | |||
+ | |||
+ | # flatten the ports | ||
+ | new_ports = [] | ||
+ | for p in get_ports(mod): | ||
p_type = p.data_type | p_type = p.data_type | ||
− | |||
if (p_type.is_named_user_type): | if (p_type.is_named_user_type): | ||
+ | print(f'... Replacing port: {p.full_name}') | ||
# Create new ports for each memeber and add them to the module | # Create new ports for each memeber and add them to the module | ||
for m in p_type.members: | for m in p_type.members: | ||
+ | portname = f"{p.base_name}_{m.base_name}" | ||
dims = [] | dims = [] | ||
for d in m.dimensions: | for d in m.dimensions: | ||
dims.append( (d.left_index, d.right_index) ) | dims.append( (d.left_index, d.right_index) ) | ||
# Create a port with the same attributes as struct memebers | # Create a port with the same attributes as struct memebers | ||
− | new_port = create_port( | + | new_port = create_port(portname, p.direction, datatype_name=m.data_type_name, dimensions=dims); |
− | + | new_ports.append(new_port) | |
− | + | ||
# Delete the old struct port | # Delete the old struct port | ||
delete_object(p) | delete_object(p) | ||
+ | |||
+ | # Insert them into top module after removing the old ports | ||
+ | for p in new_ports: | ||
+ | insert_into(p, mod) | ||
# Write out the modifications | # Write out the modifications | ||
Line 42: | Line 71: | ||
} bus_t; | } bus_t; | ||
+ | module child ( | ||
+ | input bus_t in_bus, | ||
+ | output bus_t out_bus | ||
+ | ); | ||
+ | |||
+ | assign out_bus = in_bus; | ||
+ | endmodule // child | ||
− | |||
module top #(WIDTH = 4)( | module top #(WIDTH = 4)( | ||
− | input bus_t | + | input bus_t top_in_bus, |
+ | input [0:WIDTH-1] a, | ||
output [0:WIDTH-1] d, | output [0:WIDTH-1] d, | ||
− | + | output bus_t top_out_bus | |
) ; | ) ; | ||
+ | |||
+ | child u_child ( | ||
+ | .in_bus (top_in_bus), | ||
+ | .out_bus (top_out_bus) | ||
+ | ); | ||
endmodule | endmodule | ||
Line 62: | Line 103: | ||
} bus_t; | } bus_t; | ||
+ | module child ( | ||
+ | input logic in_bus_clk, | ||
+ | input logic in_bus_rst, | ||
+ | input logic [1:0] in_bus_addr, | ||
+ | input int in_bus_data, | ||
+ | output logic out_bus_clk, | ||
+ | output logic out_bus_rst, | ||
+ | output logic [1:0] out_bus_addr, | ||
+ | output int out_bus_data | ||
+ | ); | ||
+ | |||
+ | assign out_bus_clk = in_bus_clk; | ||
+ | assign out_bus_rst = in_bus_rst; | ||
+ | assign out_bus_addr = in_bus_addr; | ||
+ | assign out_bus_data = in_bus_data; | ||
+ | |||
+ | endmodule // child | ||
− | |||
module top #(WIDTH = 4)( | module top #(WIDTH = 4)( | ||
− | + | input bus_t top_in_bus, | |
input [0:WIDTH-1] a, | input [0:WIDTH-1] a, | ||
− | + | output [0:WIDTH-1] d, | |
− | + | output bus_t top_out_bus | |
− | + | ||
− | + | ||
) ; | ) ; | ||
+ | |||
+ | child u_child ( | ||
+ | .in_bus_clk (top_in_bus.clk), | ||
+ | .in_bus_rst (top_in_bus.rst), | ||
+ | .in_bus_addr (top_in_bus.addr), | ||
+ | .in_bus_data (top_in_bus.data), | ||
+ | .out_bus_clk (top_out_bus.clk), | ||
+ | .out_bus_rst (top_out_bus.rst), | ||
+ | .out_bus_addr (top_out_bus.addr), | ||
+ | .out_bus_data (top_out_bus.data) | ||
+ | ); | ||
endmodule | endmodule | ||
</nowiki> | </nowiki> |
Latest revision as of 15:39, 8 November 2024
This example converts module with struct ports into flat ports.
from invio import * set_preference("invio_insert_ports_with_newline", 1) add_sv_file("test.sv") analyze() elaborate("top") # Convert instance of the module with struct ports into flat ports mod = get_modules("child").first for i in get_instances(mod): for p in i.portmaps: pin = p.pin if pin and pin.data_type.is_named_user_type: print(f'... Replacing portmap: {p.full_name}') portmap = '' for m in pin.data_type.members: portmap = portmap + f'.{pin.base_name}_{m.base_name} ({p.connected.first.base_name}.{m.base_name})' + ', \n' rt = create_raw_text_object(ref=p) replace_orig_text_of_object(rt, portmap[:len(portmap)-3]) # trim off the last ', ' # You will need to write out the modification and relaod to see the effect of text replacement in the parse tree. # Replace the assignment with raw text a = get_assigns(mod).first new_assign = """assign out_bus_clk = in_bus_clk; assign out_bus_rst = in_bus_rst; assign out_bus_addr = in_bus_addr; assign out_bus_data = in_bus_data; """ print(f'... Replacing assignment: {a.full_name}') replace_orig_text_of_object(a, new_assign) # flatten the ports new_ports = [] for p in get_ports(mod): p_type = p.data_type if (p_type.is_named_user_type): print(f'... Replacing port: {p.full_name}') # Create new ports for each memeber and add them to the module for m in p_type.members: portname = f"{p.base_name}_{m.base_name}" dims = [] for d in m.dimensions: dims.append( (d.left_index, d.right_index) ) # Create a port with the same attributes as struct memebers new_port = create_port(portname, p.direction, datatype_name=m.data_type_name, dimensions=dims); new_ports.append(new_port) # Delete the old struct port delete_object(p) # Insert them into top module after removing the old ports for p in new_ports: insert_into(p, mod) # Write out the modifications write_modified_file("test.sv", "test_mod.sv")
"test.sv"
typedef struct { logic clk; logic rst; logic [1:0] addr; int data; } bus_t; module child ( input bus_t in_bus, output bus_t out_bus ); assign out_bus = in_bus; endmodule // child module top #(WIDTH = 4)( input bus_t top_in_bus, input [0:WIDTH-1] a, output [0:WIDTH-1] d, output bus_t top_out_bus ) ; child u_child ( .in_bus (top_in_bus), .out_bus (top_out_bus) ); endmodule
Testcase after modification, "test_mod.sv":
typedef struct { logic clk; logic rst; logic [1:0] addr; int data; } bus_t; module child ( input logic in_bus_clk, input logic in_bus_rst, input logic [1:0] in_bus_addr, input int in_bus_data, output logic out_bus_clk, output logic out_bus_rst, output logic [1:0] out_bus_addr, output int out_bus_data ); assign out_bus_clk = in_bus_clk; assign out_bus_rst = in_bus_rst; assign out_bus_addr = in_bus_addr; assign out_bus_data = in_bus_data; endmodule // child module top #(WIDTH = 4)( input bus_t top_in_bus, input [0:WIDTH-1] a, output [0:WIDTH-1] d, output bus_t top_out_bus ) ; child u_child ( .in_bus_clk (top_in_bus.clk), .in_bus_rst (top_in_bus.rst), .in_bus_addr (top_in_bus.addr), .in_bus_data (top_in_bus.data), .out_bus_clk (top_out_bus.clk), .out_bus_rst (top_out_bus.rst), .out_bus_addr (top_out_bus.addr), .out_bus_data (top_out_bus.data) ); endmodule