diff --git a/.github/workflows/nightly_test.yml b/.github/workflows/nightly_test.yml index a57c502e0d3..c39d4d4a8f1 100644 --- a/.github/workflows/nightly_test.yml +++ b/.github/workflows/nightly_test.yml @@ -65,9 +65,9 @@ jobs: - {test: "vtr_reg_strong", cores: "16", options: "", cmake: "-DVTR_ASSERT_LEVEL=3", extra_pkgs: "libeigen3-dev"} - {test: "vtr_reg_strong_odin", cores: "16", options: "", cmake: "-DVTR_ASSERT_LEVEL=3 -DWITH_ODIN=ON", extra_pkgs: "libeigen3-dev"} - {test: "vtr_reg_strong_odin", cores: "16", options: "-skip_qor", cmake: "-DVTR_ASSERT_LEVEL=3 -DVTR_ENABLE_SANITIZE=ON -DWITH_ODIN=ON", extra_pkgs: "libeigen3-dev"} - # - {test: "vtr_reg_system_verilog", cores: "16", options: "", cmake: "-DYOSYS_F4PGA_PLUGINS=ON", extra_pkgs: ""} # Test turned off -> F4PGA conflicts with Yosys (version 42) + - {test: "vtr_reg_system_verilog", cores: "16", options: "", cmake: "-DYOSYS_F4PGA_PLUGINS=ON", extra_pkgs: ""} # Test turned off -> F4PGA conflicts with Yosys (version 42) - {test: "odin_reg_strong", cores: "16", options: "", cmake: "-DWITH_ODIN=ON", extra_pkgs: ""} - - {test: "parmys_reg_strong", cores: "16", options: "", cmake: "-DYOSYS_F4PGA_PLUGINS=OFF", extra_pkgs: ""} + - {test: "parmys_reg_strong", cores: "16", options: "", cmake: "-DYOSYS_F4PGA_PLUGINS=ON", extra_pkgs: ""} env: DEBIAN_FRONTEND: "noninteractive" diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index b738f995a69..bb6524f7f53 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -30,6 +30,7 @@ RUN apt-get update \ python-lxml \ qt5-default \ wget \ + default-jre \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/Dockerfile b/Dockerfile index 71f5129301a..2b36ac5c5e5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,7 @@ RUN apt-get update -qq \ && apt-get -y install --no-install-recommends \ wget \ ninja-build \ + default-jre \ libeigen3-dev \ libtbb-dev \ python3-pip \ diff --git a/install_apt_packages.sh b/install_apt_packages.sh index 533fdf608d5..76c705a2c34 100755 --- a/install_apt_packages.sh +++ b/install_apt_packages.sh @@ -34,6 +34,7 @@ sudo apt-get install -y \ libboost-system-dev \ libboost-python-dev \ libboost-filesystem-dev \ + default-jre \ zlib1g-dev # Required to build the documentation diff --git a/libs/EXTERNAL/CMakeLists.txt b/libs/EXTERNAL/CMakeLists.txt index a60c48958eb..556a9f8dd75 100644 --- a/libs/EXTERNAL/CMakeLists.txt +++ b/libs/EXTERNAL/CMakeLists.txt @@ -1,4 +1,5 @@ include(ExternalProject) +include(ProcessorCount) #Manually synchronized external libraries add_subdirectory(libpugixml) @@ -9,8 +10,17 @@ add_subdirectory(libsdcparse) add_subdirectory(libblifparse) add_subdirectory(libtatum) add_subdirectory(libcatch2) +#add_subdirectory(synlig) #add_subdirectory(parmys) +#Proc numbers +ProcessorCount(PROCESSOR_COUNT) + +if(PROCESSOR_COUNT EQUAL 0) + # Fallback to 1 if the processor count cannot be determined + set(PROCESSOR_COUNT 1) +endif() + #VPR_USE_SERVER is initialized in the root CMakeLists #compile sockpp only if server mode is enabled if (VPR_USE_SERVER) @@ -27,8 +37,9 @@ endif () # The VTR root CMakeFile initializes the WITH_PARMYS if (${WITH_PARMYS}) - # building Surelog and UHDM in a custom target to avoid any target conflict with VTR targets + if (${YOSYS_F4PGA_PLUGINS}) + set(SURELOG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Surelog) set(SURELOG_BINARY_DIR ${SURELOG_SOURCE_DIR}/build) set(YOSYS_F4PGA_PLUGINS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/yosys-f4pga-plugins) @@ -62,74 +73,90 @@ if (${WITH_PARMYS}) LOG_OUTPUT_ON_FAILURE ON # dependency - DEPENDS yosys + DEPENDS yosys ) - ExternalProject_Add(f4pga-plugins - # root directory for the Yosys-F4PGA-Plugins project - PREFIX "f4pga-plugins" - - GIT_REPOSITORY https://github.com/chipsalliance/yosys-f4pga-plugins.git - GIT_TAG v1.20230808 - GIT_PROGRESS TRUE - GIT_SHALLOW TRUE - - # setting source, build and install directories - SOURCE_DIR "${YOSYS_F4PGA_PLUGINS_SOURCE_DIR}" - BUILD_IN_SOURCE FALSE - INSTALL_DIR "" - - INSTALL_COMMAND "" - CONFIGURE_COMMAND "" - BUILD_COMMAND ${MAKE_PROGRAM} -C ${YOSYS_F4PGA_PLUGINS_SOURCE_DIR} - PATH=${CMAKE_BINARY_DIR}/bin/:$ENV{PATH} - UHDM_INSTALL_DIR=${CMAKE_BINARY_DIR} - BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}/f4pga-plugins/$(NAME) # NAME will be resolved by yosys-f4pga-plugins Make - YOSYS_PATH=${CMAKE_BINARY_DIR} - install -j${CUSTOM_BUILD_PARALLEL_LEVEL} - - # redirect logs to a logfile - LOG_BUILD ON - LOG_UPDATE ON - LOG_INSTALL ON - LOG_CONFIGURE OFF - LOG_OUTPUT_ON_FAILURE ON + # Synlig integration (manages Surelog and UHDM internally) + + # Synlig integration (manages Surelog and UHDM internally) + set(SYNLIG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/synlig) + + # Clone Synlig repository and ensure submodules are synced before building + ExternalProject_Add(synlig + PREFIX "synlig" + + # Clone the Synlig repository + GIT_REPOSITORY https://github.com/chipsalliance/synlig.git + GIT_TAG main + GIT_PROGRESS TRUE + GIT_SHALLOW TRUE + + # Set source and build directories + SOURCE_DIR "${SYNLIG_SOURCE_DIR}" + BUILD_IN_SOURCE FALSE + INSTALL_DIR " " + + # Sync submodules after cloning + + + UPDATE_COMMAND git submodule update --init --recursive third_party/surelog + WORKING_DIRECTORY ${SYNLIG_SOURCE_DIR} + + BUILD_COMMAND ${MAKE_PROGRAM} -C ${SYNLIG_SOURCE_DIR} install DESTDIR=${CMAKE_BINARY_DIR}/bin/synlig_install -j${PROCESSOR_COUNT} + INSTALL_COMMAND "" + CONFIGURE_COMMAND "" + + # Pass necessary paths and set environment variables + CMAKE_CACHE_ARGS + "-DCMAKE_BUILD_TYPE:STRING=Release" + "-DSURELOG_PATH=${CMAKE_BINARY_DIR}/surelog" + "-DYOSYS_PATH=${CMAKE_BINARY_DIR}/yosys" + "-DUHDM_INSTALL_DIR=${CMAKE_BINARY_DIR}" + "-DBUILD_DIR=${CMAKE_BINARY_DIR}/synlig-build" + "-DEXPORT_PATH=${CMAKE_BINARY_DIR}/synlig_install/usr/local/bin:$ENV{PATH}" + + LOG_BUILD ON + LOG_UPDATE ON + LOG_INSTALL ON + LOG_CONFIGURE OFF + LOG_OUTPUT_ON_FAILURE ON + + # Ensure dependencies like Yosys are built first + DEPENDS yosys # Ensure submodule sync runs before synlig build + ) - # dependency - DEPENDS surelog yosys - ) endif () - endif () -if (${VTR_ENABLE_CAPNPROTO}) - # Override default policy for capnproto (CMake policy version 3.1) - # Enable new IPO variables - set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) - # Enable option overrides via variables - set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) + if (${VTR_ENABLE_CAPNPROTO}) + # Override default policy for capnproto (CMake policy version 3.1) + # Enable new IPO variables + set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) - # Re-enable CXX extensions for capnproto. - set(CMAKE_CXX_EXTENSIONS ON) + # Enable option overrides via variables + set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) - # Disable capnproto tests - set(BUILD_TESTING OFF) + # Re-enable CXX extensions for capnproto. + set(CMAKE_CXX_EXTENSIONS ON) - #Since capnproto is an externally developed library/tool, we suppress all compiler warnings - CHECK_CXX_COMPILER_FLAG("-w" CXX_COMPILER_SUPPORTS_-w) - if (CXX_COMPILER_SUPPORTS_-w) - add_compile_options("-w") - endif () + # Disable capnproto tests + set(BUILD_TESTING OFF) - add_subdirectory(capnproto EXCLUDE_FROM_ALL) + #Since capnproto is an externally developed library/tool, we suppress all compiler warnings + CHECK_CXX_COMPILER_FLAG("-w" CXX_COMPILER_SUPPORTS_-w) + if (CXX_COMPILER_SUPPORTS_-w) + add_compile_options("-w") + endif () - #Some capnproto kj headers (e.g. filesystem.h) generate warnings, treat them as system headers to suppress warnings - #We suppress them here since we include the capnproto sub-tree as is and do not modify its CMakeLists.txts - target_include_directories(kj SYSTEM INTERFACE - $ - $ - ) + add_subdirectory(capnproto EXCLUDE_FROM_ALL) + + #Some capnproto kj headers (e.g. filesystem.h) generate warnings, treat them as system headers to suppress warnings + #We suppress them here since we include the capnproto sub-tree as is and do not modify its CMakeLists.txts + target_include_directories(kj SYSTEM INTERFACE + $ + $ + ) endif () # Some catch2 headers generate warnings, so treat them as system headers to suppress warnings diff --git a/vtr_flow/benchmarks/system_verilog/f4pga/README.md b/vtr_flow/benchmarks/system_verilog/f4pga/README.md index 1887a0a2681..2d3e481d3a4 100644 --- a/vtr_flow/benchmarks/system_verilog/f4pga/README.md +++ b/vtr_flow/benchmarks/system_verilog/f4pga/README.md @@ -4,4 +4,14 @@ This folder contains the `button_controller`, `pulse_width_led` and `timer` benc The benchmarks are directly copied to avoid dealing with a significant amount of code by adding the F4PGA repository as a subtree to the VTR repository. The primary purpose of these benchmarks is to utilize them in VTR GitHub CI tests to continuously monitor the functionality of the Yosys SystemVerilog and UHDM plugins. -For more information please see the ['ChipsAlliance/F4PGA'](https://github.com/chipsalliance/f4pga) Github repository. \ No newline at end of file +For more information please see the ['ChipsAlliance/F4PGA'](https://github.com/chipsalliance/f4pga) Github repository. + +## SystemVerilog File Flattening with `make_sv_flattened.py` + +The current SystemVerilog tool, **Synlig**, cannot process multiple files as input (e.g., a top module and its dependencies). To address this limitation, use the script `make_sv_flattened.py` to flatten the files into a single SystemVerilog file. This will convert any design with dependencies into one flattened SystemVerilog file, ensuring compatibility with Synlig. + +### Instructions: +1. Ensure the `make_sv_flattened.py` script is located in the folder where your SystemVerilog files (e.g., the top module and its dependencies) are gathered. +2. Run the `make_sv_flattened.py` script on the gathered files in that folder. +3. The script will output a single flattened SystemVerilog file, ready for use with Synlig. + diff --git a/vtr_flow/benchmarks/system_verilog/f4pga/button_controller/flattened_button_controller.sv b/vtr_flow/benchmarks/system_verilog/f4pga/button_controller/flattened_button_controller.sv new file mode 100644 index 00000000000..13883b1f424 --- /dev/null +++ b/vtr_flow/benchmarks/system_verilog/f4pga/button_controller/flattened_button_controller.sv @@ -0,0 +1,241 @@ +// Content from button_controller.sv +`timescale 1ns / 1ps `default_nettype none + +module top ( + input wire logic clk, + btnu, + btnc, + output logic [3:0] anode, + output logic [7:0] segment +); + + + logic sync; + logic syncToDebounce; + logic debounceToOneShot; + logic f1, f2; + logic f3, f4; + logic oneShotToCounter; + logic [7:0] counterToSevenSegment; + logic [7:0] counterToSevenSegment2; + logic oneShotToCounter2; + logic s0, s1; + debounce d0 ( + .clk(clk), + .reset(btnu), + .noisy(syncToDebounce), + .debounced(debounceToOneShot) + ); + + assign oneShotToCounter = f1 && ~f2; + + assign oneShotToCounter2 = f3 && ~f4; + + timer #(.MOD_VALUE(256), .BIT_WIDTH(8)) T0 ( + .clk(clk), + .reset(btnu), + .increment(oneShotToCounter), + .rolling_over(s0), + .count(counterToSevenSegment) + ); + + timer #(.MOD_VALUE(256), .BIT_WIDTH(8)) T1 ( + .clk(clk), + .reset(btnu), + .increment(oneShotToCounter2), + .rolling_over(s1), + .count(counterToSevenSegment2) + ); + + + display_control DC0 ( + .clk(clk), + .reset(btnu), + .dataIn({counterToSevenSegment2, counterToSevenSegment}), + .digitDisplay(4'b1111), + .digitPoint(4'b0000), + .anode(anode), + .segment(segment) + ); + + always_ff @(posedge clk) begin + + sync <= btnc; + syncToDebounce <= sync; + + f1 <= debounceToOneShot; + f2 <= f1; + + f3 <= syncToDebounce; + f4 <= f3; + end +endmodule + + +// Content from debounce.sv +`timescale 1ns / 1ps `default_nettype none + +module debounce ( + input wire logic clk, + reset, + noisy, + output logic debounced +); + + logic timerDone, clrTimer; + + typedef enum logic [1:0] { + s0, + s1, + s2, + s3, + ERR = 'X + } state_type_e; + state_type_e ns, cs; + + logic [18:0] tA; + + timer #(.MOD_VALUE(500000), .BIT_WIDTH(19)) T0 ( + .clk(clk), + .reset(clrTimer), + .increment(1'b1), + .rolling_over(timerDone), + .count(tA) + ); + + always_comb begin + ns = ERR; + clrTimer = 0; + debounced = 0; + + if (reset) ns = s0; + else + case (cs) + s0: begin + clrTimer = 1'b1; + if (noisy) ns = s1; + else ns = s0; + end + s1: + if (noisy && timerDone) ns = s2; + else if (noisy && ~timerDone) ns = s1; + else ns = s0; + s2: begin + debounced = 1'b1; + clrTimer = 1'b1; + if (noisy) ns = s2; + else ns = s3; + end + s3: begin + debounced = 1'b1; + if (~noisy && timerDone) ns = s0; + else if (~noisy && ~timerDone) ns = s3; + else ns = s2; + end + endcase + end + + always_ff @(posedge clk) cs <= ns; +endmodule + + +// Content from display_control.sv +`default_nettype none + +module display_control ( + input wire logic clk, + input wire logic reset, + input wire logic [15:0] dataIn, + input wire logic [ 3:0] digitDisplay, + input wire logic [ 3:0] digitPoint, + output logic [ 3:0] anode, + output logic [ 7:0] segment +); + + parameter integer COUNT_BITS = 17; + + logic [COUNT_BITS-1:0] count_val; + logic [ 1:0] anode_select; + logic [ 3:0] cur_anode; + logic [ 3:0] cur_data_in; + + always_ff @(posedge clk) begin + if (reset) count_val <= 0; + else count_val <= count_val + 1; + end + + assign anode_select = count_val[COUNT_BITS-1:COUNT_BITS-2]; + + assign cur_anode = + (anode_select == 2'b00) ? 4'b1110 : + (anode_select == 2'b01) ? 4'b1101 : + (anode_select == 2'b10) ? 4'b1011 : + 4'b0111; + + assign anode = cur_anode | (~digitDisplay); + + assign cur_data_in = + (anode_select == 2'b00) ? dataIn[3:0] : + (anode_select == 2'b01) ? dataIn[7:4] : + (anode_select == 2'b10) ? dataIn[11:8] : + dataIn[15:12] ; + + assign segment[7] = + (anode_select == 2'b00) ? ~digitPoint[0] : + (anode_select == 2'b01) ? ~digitPoint[1] : + (anode_select == 2'b10) ? ~digitPoint[2] : + ~digitPoint[3] ; + + assign segment[6:0] = + (cur_data_in == 0) ? 7'b1000000 : + (cur_data_in == 1) ? 7'b1111001 : + (cur_data_in == 2) ? 7'b0100100 : + (cur_data_in == 3) ? 7'b0110000 : + (cur_data_in == 4) ? 7'b0011001 : + (cur_data_in == 5) ? 7'b0010010 : + (cur_data_in == 6) ? 7'b0000010 : + (cur_data_in == 7) ? 7'b1111000 : + (cur_data_in == 8) ? 7'b0000000 : + (cur_data_in == 9) ? 7'b0010000 : + (cur_data_in == 10) ? 7'b0001000 : + (cur_data_in == 11) ? 7'b0000011 : + (cur_data_in == 12) ? 7'b1000110 : + (cur_data_in == 13) ? 7'b0100001 : + (cur_data_in == 14) ? 7'b0000110 : + 7'b0001110; + + +endmodule + + +// Content from timer.sv +`timescale 1ns / 1ps `default_nettype none + +module timer #( + parameter MOD_VALUE = 1, + parameter BIT_WIDTH = 1 +) ( + input wire logic clk, + reset, + increment, + output logic rolling_over, + output logic [BIT_WIDTH-1:0] count = 0 +); + + always_ff @(posedge clk) begin + if (reset) count <= 0; + else if (increment) begin + if (rolling_over) count <= 0; + else count <= count + 1'b1; + end + + end + + always_comb begin + if (increment && (count == MOD_VALUE - 1)) rolling_over = 1'b1; + else rolling_over = 1'b0; + end + +endmodule + + diff --git a/vtr_flow/benchmarks/system_verilog/f4pga/button_controller/make_sv_flattened.py b/vtr_flow/benchmarks/system_verilog/f4pga/button_controller/make_sv_flattened.py new file mode 100644 index 00000000000..bcc72a26634 --- /dev/null +++ b/vtr_flow/benchmarks/system_verilog/f4pga/button_controller/make_sv_flattened.py @@ -0,0 +1,65 @@ +""" +Module for flattening the SV design files. +""" +import os +import re + +def find_verilog_files(): + """Find all Verilog (.sv, .v) files in the current directory.""" + return [f for f in os.listdir('.') if f.endswith(('.sv', '.v'))] + +def identify_top_module(file_list): + """Identify the file containing the top module definition.""" + top_module_regex = re.compile(r"module\s+top\s*\(") + for file in file_list: + with open(file, 'r') as f: + for line in f: + if top_module_regex.search(line): + return file + return None + +def create_flattened_file(top_file, file_list): + """Create a flattened Verilog file with all file contents.""" + current_dir = os.path.basename(os.getcwd()) + output_file_name = f"flattened_{current_dir}.sv" + + with open(output_file_name, 'w') as output_file: + if top_file: + # Write the top module first + with open(top_file, 'r') as top_module: + output_file.write(f"// Content from {top_file}\n") + output_file.write(top_module.read()) + output_file.write("\n\n") + + # Write the rest of the files + for file in file_list: + if file != top_file: + with open(file, 'r') as verilog_file: + output_file.write(f"// Content from {file}\n") + output_file.write(verilog_file.read()) + output_file.write("\n\n") + + print(f"Flattened file created: {output_file_name}") + +def main(): + """Main function to generate the flattened Verilog file.""" + print("Searching for Verilog files...") + verilog_files = find_verilog_files() + + if not verilog_files: + print("No Verilog files found in the current directory.") + return + + print("Identifying the top module...") + top_file = identify_top_module(verilog_files) + + if top_file: + print(f"Top module found in: {top_file}") + else: + print("No top module found. Files will be combined in arbitrary order.") + + print("Creating flattened file...") + create_flattened_file(top_file, verilog_files) + +if __name__ == "__main__": + main() diff --git a/vtr_flow/benchmarks/system_verilog/f4pga/pulse_width_led/flattened_pulse_width_led.sv b/vtr_flow/benchmarks/system_verilog/f4pga/pulse_width_led/flattened_pulse_width_led.sv new file mode 100644 index 00000000000..74e32cc07fe --- /dev/null +++ b/vtr_flow/benchmarks/system_verilog/f4pga/pulse_width_led/flattened_pulse_width_led.sv @@ -0,0 +1,52 @@ +// Content from pulse_led.v +module top ( + input wire clk, + input wire [3:0] sw, + input wire [3:0] btn, + output wire pulse_red, + pulse_blue, + pulse_green +); + wire [13:0] pulse_wideR, pulse_wideB, pulse_wideG; + + assign pulse_wideR = {1'b0, sw[3:1], 10'd0}; + assign pulse_wideG = {1'b0, sw[0], btn[3:2], 10'd0}; + assign pulse_wideB = {btn[1:0], 11'd0}; + + PWM R0 ( + .clk (clk), + .pulse(pulse_red), + .width(pulse_wideR) + ); + PWM B0 ( + .clk (clk), + .pulse(pulse_green), + .width(pulse_wideB) + ); + PWM G0 ( + .clk (clk), + .pulse(pulse_blue), + .width(pulse_wideG) + ); + + +endmodule + + +// Content from PWM.v +module PWM ( + input wire clk, + input wire [13:0] width, + output reg pulse +); + + reg [13:0] counter = 0; + + always @(posedge clk) begin + counter <= counter + 1; + if (counter < width) pulse <= 1'b1; + else pulse <= 1'b0; + end +endmodule + + diff --git a/vtr_flow/benchmarks/system_verilog/f4pga/pulse_width_led/make_sv_flattened.py b/vtr_flow/benchmarks/system_verilog/f4pga/pulse_width_led/make_sv_flattened.py new file mode 100644 index 00000000000..bcc72a26634 --- /dev/null +++ b/vtr_flow/benchmarks/system_verilog/f4pga/pulse_width_led/make_sv_flattened.py @@ -0,0 +1,65 @@ +""" +Module for flattening the SV design files. +""" +import os +import re + +def find_verilog_files(): + """Find all Verilog (.sv, .v) files in the current directory.""" + return [f for f in os.listdir('.') if f.endswith(('.sv', '.v'))] + +def identify_top_module(file_list): + """Identify the file containing the top module definition.""" + top_module_regex = re.compile(r"module\s+top\s*\(") + for file in file_list: + with open(file, 'r') as f: + for line in f: + if top_module_regex.search(line): + return file + return None + +def create_flattened_file(top_file, file_list): + """Create a flattened Verilog file with all file contents.""" + current_dir = os.path.basename(os.getcwd()) + output_file_name = f"flattened_{current_dir}.sv" + + with open(output_file_name, 'w') as output_file: + if top_file: + # Write the top module first + with open(top_file, 'r') as top_module: + output_file.write(f"// Content from {top_file}\n") + output_file.write(top_module.read()) + output_file.write("\n\n") + + # Write the rest of the files + for file in file_list: + if file != top_file: + with open(file, 'r') as verilog_file: + output_file.write(f"// Content from {file}\n") + output_file.write(verilog_file.read()) + output_file.write("\n\n") + + print(f"Flattened file created: {output_file_name}") + +def main(): + """Main function to generate the flattened Verilog file.""" + print("Searching for Verilog files...") + verilog_files = find_verilog_files() + + if not verilog_files: + print("No Verilog files found in the current directory.") + return + + print("Identifying the top module...") + top_file = identify_top_module(verilog_files) + + if top_file: + print(f"Top module found in: {top_file}") + else: + print("No top module found. Files will be combined in arbitrary order.") + + print("Creating flattened file...") + create_flattened_file(top_file, verilog_files) + +if __name__ == "__main__": + main() diff --git a/vtr_flow/benchmarks/system_verilog/f4pga/timer/flattened_timer.sv b/vtr_flow/benchmarks/system_verilog/f4pga/timer/flattened_timer.sv new file mode 100644 index 00000000000..5891e940a15 --- /dev/null +++ b/vtr_flow/benchmarks/system_verilog/f4pga/timer/flattened_timer.sv @@ -0,0 +1,230 @@ +// Content from clock.sv +`timescale 1ns / 1ps `default_nettype none + +module top ( + input wire logic clk, + btnc, + sw, + output logic [3:0] anode, + output logic [7:0] segment +); + + logic [15:0] digitData; + + timer TC0 ( + .clk(clk), + .reset(btnc), + .run(sw), + .digit0(digitData[3:0]), + .digit1(digitData[7:4]), + .digit2(digitData[11:8]), + .digit3(digitData[15:12]) + ); + display_control SSC0 ( + .clk(clk), + .reset(btnc), + .dataIn(digitData), + .digitDisplay(4'b1111), + .digitPoint(4'b0100), + .anode(anode), + .segment(segment) + ); +endmodule + + +// Content from modify_count.sv +`default_nettype none + +module modify_count #( + parameter MOD_VALUE = 10 +) ( + input wire logic clk, + reset, + increment, + output logic rolling_over, + output logic [3:0] count = 0 +); + + always_ff @(posedge clk) begin + if (reset) count <= 4'b0000; + else if (increment) begin + if (rolling_over) count <= 4'b0000; + else count <= count + 4'b0001; + end + end + + always_comb begin + if (increment && (count == MOD_VALUE - 1)) rolling_over = 1'b1; + else rolling_over = 1'b0; + end + +endmodule + + +// Content from display_control.sv +`default_nettype none + + +module display_control ( + input wire logic clk, + input wire logic reset, + input wire logic [15:0] dataIn, + input wire logic [ 3:0] digitDisplay, + input wire logic [ 3:0] digitPoint, + output logic [ 3:0] anode, + output logic [ 7:0] segment +); + + parameter integer COUNT_BITS = 17; + + logic [COUNT_BITS-1:0] count_val; + logic [ 1:0] anode_select; + logic [ 3:0] cur_anode; + logic [ 3:0] cur_data_in; + + + always_ff @(posedge clk) begin + if (reset) count_val <= 0; + else count_val <= count_val + 1; + end + + assign anode_select = count_val[COUNT_BITS-1:COUNT_BITS-2]; + + assign cur_anode = + (anode_select == 2'b00) ? 4'b1110 : + (anode_select == 2'b01) ? 4'b1101 : + (anode_select == 2'b10) ? 4'b1011 : + 4'b0111; + + assign anode = cur_anode | (~digitDisplay); + + assign cur_data_in = + (anode_select == 2'b00) ? dataIn[3:0] : + (anode_select == 2'b01) ? dataIn[7:4] : + (anode_select == 2'b10) ? dataIn[11:8] : + dataIn[15:12] ; + + assign segment[7] = + (anode_select == 2'b00) ? ~digitPoint[0] : + (anode_select == 2'b01) ? ~digitPoint[1] : + (anode_select == 2'b10) ? ~digitPoint[2] : + ~digitPoint[3] ; + + assign segment[6:0] = + (cur_data_in == 0) ? 7'b1000000 : + (cur_data_in == 1) ? 7'b1111001 : + (cur_data_in == 2) ? 7'b0100100 : + (cur_data_in == 3) ? 7'b0110000 : + (cur_data_in == 4) ? 7'b0011001 : + (cur_data_in == 5) ? 7'b0010010 : + (cur_data_in == 6) ? 7'b0000010 : + (cur_data_in == 7) ? 7'b1111000 : + (cur_data_in == 8) ? 7'b0000000 : + (cur_data_in == 9) ? 7'b0010000 : + (cur_data_in == 10) ? 7'b0001000 : + (cur_data_in == 11) ? 7'b0000011 : + (cur_data_in == 12) ? 7'b1000110 : + (cur_data_in == 13) ? 7'b0100001 : + (cur_data_in == 14) ? 7'b0000110 : + 7'b0001110; + + +endmodule + + +// Content from timer.sv +`timescale 1ns / 1ps `default_nettype none + +module timer ( + input wire logic clk, + reset, + run, + output logic [3:0] digit0, + digit1, + digit2, + digit3 +); + + logic inc0, inc1, inc2, inc3, inc4; + + logic [23:0] timerCount; + + modify_count #( + .MOD_VALUE(10) + ) M0 ( + .clk(clk), + .reset(reset), + .increment(inc0), + .rolling_over(inc1), + .count(digit0) + ); + modify_count #( + .MOD_VALUE(10) + ) M1 ( + .clk(clk), + .reset(reset), + .increment(inc1), + .rolling_over(inc2), + .count(digit1) + ); + modify_count #( + .MOD_VALUE(10) + ) M2 ( + .clk(clk), + .reset(reset), + .increment(inc2), + .rolling_over(inc3), + .count(digit2) + ); + modify_count #( + .MOD_VALUE(6) + ) M3 ( + .clk(clk), + .reset(reset), + .increment(inc3), + .rolling_over(inc4), + .count(digit3) + ); + + time_counter #( + .MOD_VALUE(1000000) + ) T0 ( + .clk(clk), + .reset(reset), + .increment(run), + .rolling_over(inc0), + .count(timerCount) + ); +endmodule + + +// Content from time_counter.sv +`timescale 1ns / 1ps `default_nettype none + +module time_counter #( + parameter MOD_VALUE = 1000000 +) ( + input wire logic clk, + reset, + increment, + output logic rolling_over, + output logic [23:0] count = 0 +); + + always_ff @(posedge clk) begin + if (reset) count <= 0; + else if (increment) begin + if (rolling_over) count <= 0; + else count <= count + 1'b1; + end + + end + + always_comb begin + if (increment && (count == MOD_VALUE - 1)) rolling_over = 1'b1; + else rolling_over = 1'b0; + end + +endmodule + + diff --git a/vtr_flow/benchmarks/system_verilog/f4pga/timer/make_sv_flattened.py b/vtr_flow/benchmarks/system_verilog/f4pga/timer/make_sv_flattened.py new file mode 100644 index 00000000000..bcc72a26634 --- /dev/null +++ b/vtr_flow/benchmarks/system_verilog/f4pga/timer/make_sv_flattened.py @@ -0,0 +1,65 @@ +""" +Module for flattening the SV design files. +""" +import os +import re + +def find_verilog_files(): + """Find all Verilog (.sv, .v) files in the current directory.""" + return [f for f in os.listdir('.') if f.endswith(('.sv', '.v'))] + +def identify_top_module(file_list): + """Identify the file containing the top module definition.""" + top_module_regex = re.compile(r"module\s+top\s*\(") + for file in file_list: + with open(file, 'r') as f: + for line in f: + if top_module_regex.search(line): + return file + return None + +def create_flattened_file(top_file, file_list): + """Create a flattened Verilog file with all file contents.""" + current_dir = os.path.basename(os.getcwd()) + output_file_name = f"flattened_{current_dir}.sv" + + with open(output_file_name, 'w') as output_file: + if top_file: + # Write the top module first + with open(top_file, 'r') as top_module: + output_file.write(f"// Content from {top_file}\n") + output_file.write(top_module.read()) + output_file.write("\n\n") + + # Write the rest of the files + for file in file_list: + if file != top_file: + with open(file, 'r') as verilog_file: + output_file.write(f"// Content from {file}\n") + output_file.write(verilog_file.read()) + output_file.write("\n\n") + + print(f"Flattened file created: {output_file_name}") + +def main(): + """Main function to generate the flattened Verilog file.""" + print("Searching for Verilog files...") + verilog_files = find_verilog_files() + + if not verilog_files: + print("No Verilog files found in the current directory.") + return + + print("Identifying the top module...") + top_file = identify_top_module(verilog_files) + + if top_file: + print(f"Top module found in: {top_file}") + else: + print("No top module found. Files will be combined in arbitrary order.") + + print("Creating flattened file...") + create_flattened_file(top_file, verilog_files) + +if __name__ == "__main__": + main() diff --git a/vtr_flow/misc/yosys/synthesis.tcl b/vtr_flow/misc/yosys/synthesis.tcl index 5015d587055..836224eb34f 100644 --- a/vtr_flow/misc/yosys/synthesis.tcl +++ b/vtr_flow/misc/yosys/synthesis.tcl @@ -7,7 +7,15 @@ read_verilog -nomem2reg +/parmys/vtr_primitives.v setattr -mod -set keep_hierarchy 1 single_port_ram setattr -mod -set keep_hierarchy 1 dual_port_ram -puts "Using parmys as partial mapper" +# synlig path error handling +if {[catch {set synlig $::env(synlig_exe_path)} err]} { + puts "Error: $err" + puts "synlig_exe_path is not set" +} else { + set synlig $::env(synlig_exe_path) + puts "Using parmys as partial mapper" +} + # arch file: QQQ # input files: [XXX] @@ -18,15 +26,14 @@ puts "Using parmys as partial mapper" parmys_arch -a QQQ if {$env(PARSER) == "surelog" } { - puts "Using Yosys read_uhdm command" - plugin -i systemverilog - yosys -import - read_uhdm XXX + puts "Using Synlig read_uhdm command" + + exec $synlig -p "read_uhdm XXX" + } elseif {$env(PARSER) == "system-verilog" } { - puts "Using Yosys read_systemverilog command" - plugin -i systemverilog - yosys -import - read_systemverilog XXX + puts "Using Synlig read_systemverilog " + exec $synlig -p "read_systemverilog XXX" + } elseif {$env(PARSER) == "default" } { puts "Using Yosys read_verilog command" read_verilog -sv -nolatches XXX @@ -66,7 +73,23 @@ techmap -map +/parmys/aldffe2dff.v opt -full -parmys -a QQQ -nopass -c CCC YYY +#parmys -a QQQ -nopass -c CCC YYY +#parmys -a QQQ -c CCC YYY +#memory -nomap +#flatten + + +# Separate opt for Parmys execution(verilog or system-verilog) +if {$env(PARSER) == "default"} { + puts "Running Parmys with disables additional passes " + parmys -a QQQ -nopass -c CCC YYY + +} elseif {$env(PARSER) == "system-verilog" || $env(PARSER) == "surelog"} { + puts "Running Parmys with Additional Passes Resolve Conflicts" + parmys -a QQQ -c CCC YYY + memory -nomap + flatten +} opt -full @@ -75,7 +98,6 @@ opt -fast dffunmap opt -fast -noff - #autoname stat diff --git a/vtr_flow/scripts/python_libs/vtr/parmys/parmys.py b/vtr_flow/scripts/python_libs/vtr/parmys/parmys.py index cef45626828..e11478e8f18 100644 --- a/vtr_flow/scripts/python_libs/vtr/parmys/parmys.py +++ b/vtr_flow/scripts/python_libs/vtr/parmys/parmys.py @@ -232,6 +232,13 @@ def run( odin_config_full_path, ) + # Set the synlig exe script path in the environment variable + # (handle if it is not set or system-verilog OFF) + try: + os.environ["synlig_exe_path"] = str(vtr.paths.synlig_exe_path) + except KeyError: + os.environ["synlig_exe_path"] = "/dummy/path" + # set the parser if parmys_args["parser"] in YOSYS_PARSERS: os.environ["PARSER"] = parmys_args["parser"] diff --git a/vtr_flow/scripts/python_libs/vtr/paths.py b/vtr_flow/scripts/python_libs/vtr/paths.py index 2df9317c81c..5f0888c328f 100644 --- a/vtr_flow/scripts/python_libs/vtr/paths.py +++ b/vtr_flow/scripts/python_libs/vtr/paths.py @@ -22,6 +22,10 @@ yosys_tcl_path = vtr_flow_path / "misc" / "yosys" yosys_script_path = yosys_tcl_path / "synthesis.tcl" +# Synlig paths +synlig_path = root_path/"build"/"bin"/"synlig_install" +synlig_exe_path = synlig_path / "usr"/"local"/"bin"/"synlig" + # PARMYS paths parmys_path = root_path / "parmys" parmys_verify_path = parmys_path / "verify_parmys.sh" diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_button_controller/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_button_controller/config/config.txt index f20ab703070..5005a12aaca 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_button_controller/config/config.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_button_controller/config/config.txt @@ -12,12 +12,14 @@ archs_dir=arch/timing # Add circuits to list to sweep -include_list_add=display_control.sv -include_list_add=timer.sv -include_list_add=debounce.sv +#include_list_add=display_control.sv +#include_list_add=timer.sv +#include_list_add=debounce.sv # Add circuits to list to sweep -circuit_list_add=button_controller.sv +#circuit_list_add=button_controller.sv + +circuit_list_add=flattened_button_controller.sv # Add architectures to list to sweep diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_pulse_width_led/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_pulse_width_led/config/config.txt index 6c7dd369b44..c59221ce1d4 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_pulse_width_led/config/config.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_pulse_width_led/config/config.txt @@ -12,11 +12,12 @@ archs_dir=arch/timing # Add circuits to list to sweep -include_list_add=PWM.v +#include_list_add=PWM.v # Add circuits to list to sweep -circuit_list_add=pulse_led.v +#circuit_list_add=pulse_led.v +circuit_list_add=flattened_pulse_width_led.sv # Add architectures to list to sweep arch_list_add=k6_frac_N10_frac_chain_mem32K_40nm.xml diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_timer/config/config.txt b/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_timer/config/config.txt index 6b753bb4aa6..c2c180dab1d 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_timer/config/config.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/f4pga_timer/config/config.txt @@ -12,13 +12,13 @@ archs_dir=arch/timing # Add circuits to list to sweep -include_list_add=timer.sv -include_list_add=display_control.sv -include_list_add=time_counter.sv -include_list_add=modify_count.sv +#include_list_add=timer.sv +#include_list_add=display_control.sv +#include_list_add=time_counter.sv +#include_list_add=modify_count.sv # Add circuits to list to sweep -circuit_list_add=clock.sv +circuit_list_add=flattened_timer.sv # Add architectures to list to sweep diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/task_list.txt b/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/task_list.txt index 27a696e2c05..509f77a6434 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/task_list.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_system_verilog/task_list.txt @@ -1,3 +1,3 @@ regression_tests/vtr_reg_system_verilog/f4pga_button_controller/ regression_tests/vtr_reg_system_verilog/f4pga_pulse_width_led/ -regression_tests/vtr_reg_system_verilog/f4pga_timer/ \ No newline at end of file +regression_tests/vtr_reg_system_verilog/f4pga_timer/