From 794c0b657c4bef09a9ce27f3bf8304e397b75aa5 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 28 Sep 2024 11:14:50 -0700 Subject: [PATCH 1/8] Next installment of making the SConstruct files pyling compatible. Fixed these warnings: * line too long * fixme * imported by unused * f-string is missing placeholders --- apio/resources/ecp5/SConstruct | 86 ++++++++++++++++++--------------- apio/resources/gowin/SConstruct | 83 +++++++++++++++++-------------- apio/resources/ice40/SConstruct | 78 +++++++++++++++++------------- tox.ini | 14 ++++-- 4 files changed, 148 insertions(+), 113 deletions(-) diff --git a/apio/resources/ecp5/SConstruct b/apio/resources/ecp5/SConstruct index 4ff44842..2d17411a 100644 --- a/apio/resources/ecp5/SConstruct +++ b/apio/resources/ecp5/SConstruct @@ -7,25 +7,22 @@ # -- Licence GPLv2 # ---------------------------------------------------------------------- +# pylint: disable=fixme + import os import re from platform import system -from apio import scons_util from SCons.Script import ( Builder, Action, - DefaultEnvironment, Default, AlwaysBuild, GetOption, Exit, COMMAND_LINE_TARGETS, ARGUMENTS, - Variables, - Help, Glob, ) -from SCons.Script.SConscript import SConsEnvironment from apio.scons_util import ( get_constraint_file, error, @@ -115,7 +112,10 @@ env.Append(BUILDERS={"Synth": synth_builder}) # -- Place and route Builder. pnr_builder = Builder( - action="nextpnr-ecp5 --{0} --package {2} --json $SOURCE --textcfg $TARGET --lpf {3} {4} --timing-allow-fail --force".format( + action=( + "nextpnr-ecp5 --{0} --package {2} --json $SOURCE --textcfg $TARGET " + "--lpf {3} {4} --timing-allow-fail --force" + ).format( FPGA_TYPE_PARAM, FPGA_SIZE, FPGA_PACK, @@ -139,7 +139,10 @@ env.Append(BUILDERS={"Bin": bitstream_builder}) # -- No time analysis report implemented for the ECP5 family time_rpt_builder = Builder( - action='echo "Time analysis report is not impelemnted for the ECP5 family." > $TARGET', + action=( + 'echo "Time analysis report is not impelemnted for the ECP5 family." ' + "> $TARGET" + ), suffix=".rpt", src_suffix=".config", ) @@ -168,32 +171,28 @@ time_target = env.Alias("time", time_rpt_target) def iverilog_generator(source, target, env, for_signature): """Constructs dynamically a commands for iverlog targets builders.""" - target_name, _ = os.path.splitext( - str(target[0]) - ) # E.g. "my_module" or"my_module_tb" - # Testbenches use the value macro VCD_OUTPUT to know the name of the waves output file. - # We also pass a dummy when the verify command to avoid a warning about the undefined macro. + # E.g. "my_module" or "my_module_tb" + target_name, _ = os.path.splitext(str(target[0])) + # Testbenches use the value macro VCD_OUTPUT to know the name of the waves + # output file. We also pass a dummy when the verify command to avoid a + # warning about the undefined macro. is_testbench = target_name.upper().endswith("_TB") is_verify = "verify" in COMMAND_LINE_TARGETS vcd_output_flag = ( - f"-D VCD_OUTPUT=dummy_vcd_output" + "-D VCD_OUTPUT=dummy_vcd_output" if is_verify else f"-D VCD_OUTPUT={target_name}" if is_testbench else "" ) verbose_flag = "-v" if VERBOSE_ALL else "" - # If running a testbench with the sim command, we define the macro INTERACTIVE_SIM that - # allows the testbench to supress assertions so we can examine the waves in gtkwave. - # For example, with an assertion macro like this one that fails when running apio test. - # `define EXPECT(signal, value) \ - # if (signal !== value) begin \ - # $display("ASSERTION FAILED in %m: signal != value"); \ - # `ifndef INTERACTIVE_SIM \ - # $fatal; \ - # `endif \ - # end + # The INTERACTIVE_SIM macro allow testbenchs to distinguish between an + # automatic simulation (apio test) and interactive simulation (apio sim), + # For example, for continuing despire errors in interactive mode. is_interactive_sim = is_testbench and "sim" in COMMAND_LINE_TARGETS - interactive_sim_flag = f"-D INTERACTIVE_SIM" if is_interactive_sim else "" - result = 'iverilog {0} {1} -o $TARGET {2} {3} -D NO_INCLUDES "{3}/ecp5/cells_bb.v" "{4}" $SOURCES'.format( + interactive_sim_flag = "-D INTERACTIVE_SIM" if is_interactive_sim else "" + result = ( + "iverilog {0} {1} -o $TARGET {2} {3} -D NO_INCLUDES " + '"{3}/ecp5/cells_bb.v" "{4}" $SOURCES' + ).format( IVER_PATH, verbose_flag, vcd_output_flag, @@ -213,7 +212,11 @@ iverilog_builder = Builder( env.Append(BUILDERS={"IVerilog": iverilog_builder}) dot_builder = Builder( - action='yosys -f verilog -p "show -format dot -colors 1 -prefix hardware {0}" {1} $SOURCES'.format( + action=( + "yosys -f verilog -p " + '"show -format dot -colors 1 -prefix hardware {0}" ' + "{1} $SOURCES" + ).format( TOP_MODULE if TOP_MODULE else "unknown_top", "" if VERBOSE_ALL else "-q", ), @@ -260,17 +263,18 @@ if "sim" in COMMAND_LINE_TARGETS: # Explicit testbench file name is given via --testbench. sim_testbench = TESTBENCH else: - # No --testbench flag was specified. If there is exactly one testbench then pick - # it, otherwise fail. + # No --testbench flag was specified. If there is exactly one testbench + # then pick it, otherwise fail. if len(list_tb) == 0: fatal_error(env, "No testbench found for simulation.") if len(list_tb) > 1: - # TODO: consider to allow specifying the default testbench in apio.ini. + # TODO: consider to allow specifying the default testbench + # in apio.ini. error( env, - "Found {} testbranches, please use the --testbench flag.".format( - len(list_tb) - ), + ( + "Found {} testbranches, please use the --testbench flag." + ).format(len(list_tb)), ) for tb in list_tb: print("- {}".format(tb)) @@ -304,7 +308,8 @@ if "sim" in COMMAND_LINE_TARGETS: if "test" in COMMAND_LINE_TARGETS: assert "sim" not in COMMAND_LINE_TARGETS, COMMAND_LINE_TARGETS if TESTBENCH: - # Explicit testbench file name is given via --testbench. We test just that one. + # Explicit testbench file name is given via --testbench. We test just + # that one. test_tbs = [TESTBENCH] else: # No --testbench flag specified. We will test all them. @@ -313,13 +318,14 @@ if "test" in COMMAND_LINE_TARGETS: test_tbs = list_tb # All testbenches. tests = [] # Targets of all tests for test_tb in test_tbs: - # Create a list of source files. All the modules + the current testbench. + # Create a list of source files. All the modules + the current + # testbench. src_test = [] src_test.extend(src_synth) # All the .v files. src_test.append(test_tb) # Create the targets for the 'out' and 'vcd' files of the testbench. - # NOTE: Remove the two AlwaysBuild() calls below for an incremental test. Fast, correct, - # but may confuse the user seeing nothing happens. + # NOTE: Remove the two AlwaysBuild() calls below for an incremental + # test. Fast, correct, but may confuse the user seeing nothing happens. test_name, _ = os.path.splitext(test_tb) # e.g. my_module_tb test_out_target = env.IVerilog(test_name, src_test) AlwaysBuild(test_out_target) @@ -327,7 +333,8 @@ if "test" in COMMAND_LINE_TARGETS: AlwaysBuild(test_vcd_target) test_target = env.Alias(test_name, [test_out_target, test_vcd_target]) tests.append(test_target) - # Create a target for the test command that depends on all the test targets. + # Create a target for the test command that depends on all the test + # targets. tests_target = env.Alias("test", tests) AlwaysBuild(tests_target) @@ -353,7 +360,10 @@ env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) # -- Verilator builder verilator_builder = Builder( - action='verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD -Wno-MULTITOP {0} {1} {2} {3} $SOURCES "{4}"'.format( + action=( + "verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD " + '-Wno-MULTITOP {0} {1} {2} {3} $SOURCES "{4}"' + ).format( "-Wall" if VERILATOR_ALL else "", "-Wno-style" if VERILATOR_NO_STYLE else "", VERILATOR_PARAM_STR, diff --git a/apio/resources/gowin/SConstruct b/apio/resources/gowin/SConstruct index 47276693..b3032284 100644 --- a/apio/resources/gowin/SConstruct +++ b/apio/resources/gowin/SConstruct @@ -7,25 +7,22 @@ # -- Licence GPLv2 # ---------------------------------------------------------------------- +# pylint: disable=fixme + import os import re from platform import system -from apio import scons_util from SCons.Script import ( Builder, Action, - DefaultEnvironment, Default, AlwaysBuild, GetOption, Exit, COMMAND_LINE_TARGETS, ARGUMENTS, - Variables, - Help, Glob, ) -from SCons.Script.SConscript import SConsEnvironment from apio.scons_util import ( get_constraint_file, error, @@ -98,7 +95,9 @@ CST = get_constraint_file(env, ".cst", TOP_MODULE) # -- Synthesizing Builder synth_builder = Builder( - action='yosys -D LEDS_NR=6 -p "synth_gowin {0} -json $TARGET" {1} $SOURCES'.format( + action=( + 'yosys -D LEDS_NR=6 -p "synth_gowin {0} -json $TARGET" {1} $SOURCES' + ).format( ("-top " + TOP_MODULE) if TOP_MODULE else "", "" if VERBOSE_ALL or VERBOSE_YOSYS else "-q", ), @@ -110,7 +109,10 @@ env.Append(BUILDERS={"Synth": synth_builder}) # -- Place and route Builder. pnr_builder = Builder( - action="nextpnr-himbaechel --device {0} --json $SOURCE --write $TARGET --vopt family={5} --vopt cst={3} {4}".format( + action=( + "nextpnr-himbaechel --device {0} --json $SOURCE --write $TARGET " + "--vopt family={5} --vopt cst={3} {4}" + ).format( FPGA_MODEL, FPGA_SIZE, FPGA_PACK, @@ -134,7 +136,10 @@ env.Append(BUILDERS={"Bin": bitstream_builder}) # -- Time report builder # https://github.com/cliffordwolf/icestorm/issues/57 time_rpt_builder = Builder( - action='echo "Time analysis report is not impelemnted for the Gowin family." > $TARGET', + action=( + 'echo "Time analysis report is not impelemnted for the Gowin family." ' + "> $TARGET" + ), suffix=".rpt", src_suffix=".pnr.json", ) @@ -168,31 +173,24 @@ time_target = env.Alias("time", rpt_target) def iverilog_generator(source, target, env, for_signature): """Constructs dynamically a commands for iverlog targets builders.""" - target_name, _ = os.path.splitext( - str(target[0]) - ) # E.g. "my_module" or"my_module_tb" - # Testbenches use the value macro VCD_OUTPUT to know the name of the waves output file. - # We also pass a dummy when the verify command to avoid a warning about the undefined macro. + # E.g. "my_module" or"my_module_tb" + target_name, _ = os.path.splitext(str(target[0])) + # Testbenches use the macro VCD_OUTPUT to know the name of the waves + # output file.We also pass a dummy when the verify command to avoid a + # warning about the undefined macro. is_testbench = target_name.upper().endswith("_TB") is_verify = "verify" in COMMAND_LINE_TARGETS vcd_output_flag = ( - f"-D VCD_OUTPUT=dummy_vcd_output" + "-D VCD_OUTPUT=dummy_vcd_output" if is_verify else f"-D VCD_OUTPUT={target_name}" if is_testbench else "" ) verbose_flag = "-v" if VERBOSE_ALL else "" - # If running a testbench with the sim command, we define the macro INTERACTIVE_SIM that - # allows the testbench to supress assertions so we can examine the waves in gtkwave. - # For example, with an assertion macro like this one that fails when running apio test. - # `define EXPECT(signal, value) \ - # if (signal !== value) begin \ - # $display("ASSERTION FAILED in %m: signal != value"); \ - # `ifndef INTERACTIVE_SIM \ - # $fatal; \ - # `endif \ - # end + # The INTERACTIVE_SIM macro allow testbenchs to distinguish between an + # automatic simulation (apio test) and interactive simulation (apio sim), + # For example, for continuing despire errors in interactive mode. is_interactive_sim = is_testbench and "sim" in COMMAND_LINE_TARGETS - interactive_sim_flag = f"-D INTERACTIVE_SIM" if is_interactive_sim else "" + interactive_sim_flag = "-D INTERACTIVE_SIM" if is_interactive_sim else "" result = 'iverilog {0} {1} -o $TARGET {2} {3} "{4}" $SOURCES'.format( IVER_PATH, verbose_flag, @@ -213,7 +211,10 @@ iverilog_builder = Builder( env.Append(BUILDERS={"IVerilog": iverilog_builder}) dot_builder = Builder( - action='yosys -f verilog -p "show -format dot -colors 1 -prefix hardware {0}" {1} $SOURCES'.format( + action=( + 'yosys -f verilog -p "show -format dot -colors 1 -prefix hardware ' + '{0}" {1} $SOURCES' + ).format( TOP_MODULE if TOP_MODULE else "unknown_top", "" if VERBOSE_ALL else "-q", ), @@ -260,16 +261,17 @@ if "sim" in COMMAND_LINE_TARGETS: # Explicit testbench file name is given via --testbench. sim_testbench = TESTBENCH else: - # No --testbench flag specified. If there is exactly one testbench then pick - # it, otherwise fail. + # No --testbench flag specified. If there is exactly one testbench then + # pick it, otherwise fail. if len(list_tb) == 0: fatal_error(env, "No testbench found for simulation.") if len(list_tb) > 1: - # TODO: consider to allow specifying the default testbench in apio.ini. + # TODO: consider to allow specifying the default testbench + # in apio.ini. error( - "Found {} testbranches, please use the --testbench flag.".format( - len(list_tb) - ) + ( + "Found {} testbranches, please use the --testbench flag." + ).format(len(list_tb)) ) for tb in list_tb: print("- {}".format(tb)) @@ -303,7 +305,8 @@ if "sim" in COMMAND_LINE_TARGETS: if "test" in COMMAND_LINE_TARGETS: assert "sim" not in COMMAND_LINE_TARGETS, COMMAND_LINE_TARGETS if TESTBENCH: - # Explicit testbench file name is given via --testbench. We test just that one. + # Explicit testbench file name is given via --testbench. We test just + # that one. test_tbs = [TESTBENCH] else: # No --testbench flag specified. We will test all them. @@ -312,12 +315,14 @@ if "test" in COMMAND_LINE_TARGETS: test_tbs = list_tb # All testbenches. tests = [] # Targets of all tests for test_tb in test_tbs: - # Create a list of source files. All the modules + the current testbench. + # Create a list of source files. All the modules + the current + # testbench. src_test = [] src_test.extend(src_synth) # All the .v files. src_test.append(test_tb) # Create the targets for the 'out' and 'vcd' files of the testbench. - # NOTE: Remove the two AlwaysBuild() calls below for an incremental test. Fast, correct, + # NOTE: Remove the two AlwaysBuild() calls below for an incremental + # test. Fast, correct, # but may confuse the user seeing nothing happens. test_name, _ = os.path.splitext(test_tb) # e.g. my_module_tb test_out_target = env.IVerilog(test_name, src_test) @@ -326,7 +331,8 @@ if "test" in COMMAND_LINE_TARGETS: AlwaysBuild(test_vcd_target) test_target = env.Alias(test_name, [test_out_target, test_vcd_target]) tests.append(test_target) - # Create a target for the test command that depends on all the test targets. + # Create a target for the test command that depends on all the test + # targets. tests_target = env.Alias("test", tests) AlwaysBuild(tests_target) @@ -352,7 +358,10 @@ env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) # -- Verilator builder verilator_builder = Builder( - action='verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD -Wno-MULTITOP {0} {1} {2} {3} $SOURCES "{4}"'.format( + action=( + "verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD " + '-Wno-MULTITOP {0} {1} {2} {3} $SOURCES "{4}"' + ).format( "-Wall" if VERILATOR_ALL else "", "-Wno-style" if VERILATOR_NO_STYLE else "", VERILATOR_PARAM_STR, diff --git a/apio/resources/ice40/SConstruct b/apio/resources/ice40/SConstruct index 092c47b9..6792bc55 100644 --- a/apio/resources/ice40/SConstruct +++ b/apio/resources/ice40/SConstruct @@ -7,21 +7,20 @@ # -- Licence GPLv2 # ---------------------------------------------------------------------- +# pylint: disable=fixme + import os import re from platform import system from SCons.Script import ( Builder, Action, - DefaultEnvironment, Default, AlwaysBuild, GetOption, Exit, COMMAND_LINE_TARGETS, ARGUMENTS, - Variables, - Help, Glob, ) from apio.scons_util import ( @@ -106,7 +105,10 @@ env.Append(BUILDERS={"Synth": synth_builder}) # -- Place and route Builder. pnr_builder = Builder( - action="nextpnr-ice40 --{0}{1} --package {2} --json $SOURCE --asc $TARGET --pcf {3} {4}".format( + action=( + "nextpnr-ice40 --{0}{1} --package {2} --json $SOURCE --asc $TARGET " + "--pcf {3} {4}" + ).format( FPGA_TYPE, FPGA_SIZE, FPGA_PACK, @@ -163,32 +165,28 @@ time_target = env.Alias("time", rpt_target) def iverilog_generator(source, target, env, for_signature): """Constructs dynamically a commands for iverlog targets builders.""" - target_name, _ = os.path.splitext( - str(target[0]) - ) # E.g. "my_module" or"my_module_tb" - # Testbenches use the value macro VCD_OUTPUT to know the name of the waves output file. - # We also pass a dummy when the verify command to avoid a warning about the undefined macro. + # E.g. "my_module" or "my_module_tb" + target_name, _ = os.path.splitext(str(target[0])) + # Testbenches use the macro VCD_OUTPUT to know the name of the waves + # output file.We also pass a dummy when the verify command to avoid a + # warning about the undefined macro. is_testbench = target_name.upper().endswith("_TB") is_verify = "verify" in COMMAND_LINE_TARGETS vcd_output_flag = ( - f"-D VCD_OUTPUT=dummy_vcd_output" + "-D VCD_OUTPUT=dummy_vcd_output" if is_verify else f"-D VCD_OUTPUT={target_name}" if is_testbench else "" ) verbose_flag = "-v" if VERBOSE_ALL else "" - # If running a testbench with the sim command, we define the macro INTERACTIVE_SIM that - # allows the testbench to supress assertions so we can examine the waves in gtkwave. - # For example, with an assertion macro like this one that fails when running apio test. - # `define EXPECT(signal, value) \ - # if (signal !== value) begin \ - # $display("ASSERTION FAILED in %m: signal != value"); \ - # `ifndef INTERACTIVE_SIM \ - # $fatal; \ - # `endif \ - # end + # The INTERACTIVE_SIM macro allow testbenchs to distinguish between an + # automatic simulation (apio test) and interactive simulation (apio sim), + # For example, for continuing despire errors in interactive mode. is_interactive_sim = is_testbench and "sim" in COMMAND_LINE_TARGETS - interactive_sim_flag = f"-D INTERACTIVE_SIM" if is_interactive_sim else "" - result = 'iverilog {0} {1} -o $TARGET {2} {3} -D NO_ICE40_DEFAULT_ASSIGNMENTS "{4}" $SOURCES'.format( + interactive_sim_flag = "-D INTERACTIVE_SIM" if is_interactive_sim else "" + result = ( + "iverilog {0} {1} -o $TARGET {2} {3} -D NO_ICE40_DEFAULT_ASSIGNMENTS " + '"{4}" $SOURCES' + ).format( IVER_PATH, verbose_flag, vcd_output_flag, @@ -208,7 +206,10 @@ iverilog_builder = Builder( env.Append(BUILDERS={"IVerilog": iverilog_builder}) dot_builder = Builder( - action='yosys -f verilog -p "show -format dot -colors 1 -prefix hardware {0}" {1} $SOURCES'.format( + action=( + 'yosys -f verilog -p "show -format dot -colors 1 ' + '-prefix hardware {0}" {1} $SOURCES' + ).format( TOP_MODULE if TOP_MODULE else "unknown_top", "" if VERBOSE_ALL else "-q", ), @@ -255,17 +256,18 @@ if "sim" in COMMAND_LINE_TARGETS: # Explicit testbench file name is given via --testbench. sim_testbench = TESTBENCH else: - # No --testbench flag specified. If there is exactly one testbench then pick - # it, otherwise fail. + # No --testbench flag specified. If there is exactly one testbench then + # pick it, otherwise fail. if len(list_tb) == 0: fatal_error(env, "No testbench found for simulation.") if len(list_tb) > 1: - # TODO: consider to allow specifying the default testbench in apio.ini. + # TODO: consider to allow specifying the default testbench in + # apio.ini. error( env, - "Found {} testbranches, please use the --testbench flag.".format( - len(list_tb) - ), + ( + "Found {} testbranches, please use the --testbench flag." + ).format(len(list_tb)), ) for tb in list_tb: print("- {}".format(tb)) @@ -299,7 +301,8 @@ if "sim" in COMMAND_LINE_TARGETS: if "test" in COMMAND_LINE_TARGETS: assert "sim" not in COMMAND_LINE_TARGETS, COMMAND_LINE_TARGETS if TESTBENCH: - # Explicit testbench file name is given via --testbench. We test just that one. + # Explicit testbench file name is given via --testbench. We test just + # that one. test_tbs = [TESTBENCH] else: # No --testbench flag specified. We will test all them. @@ -308,12 +311,14 @@ if "test" in COMMAND_LINE_TARGETS: test_tbs = list_tb # All testbenches. tests = [] # Targets of all tests for test_tb in test_tbs: - # Create a list of source files. All the modules + the current testbench. + # Create a list of source files. All the modules + the current + # testbench. src_test = [] src_test.extend(src_synth) # All the .v files. src_test.append(test_tb) # Create the targets for the 'out' and 'vcd' files of the testbench. - # NOTE: Remove the two AlwaysBuild() calls below for an incremental test. Fast, correct, + # NOTE: Remove the two AlwaysBuild() calls below for an incremental + # test. Fast, correct, # but may confuse the user seeing nothing happens. test_name, _ = os.path.splitext(test_tb) # e.g. my_module_tb test_out_target = env.IVerilog(test_name, src_test) @@ -322,7 +327,8 @@ if "test" in COMMAND_LINE_TARGETS: AlwaysBuild(test_vcd_target) test_target = env.Alias(test_name, [test_out_target, test_vcd_target]) tests.append(test_target) - # Create a target for the test command that depends on all the test targets. + # Create a target for the test command that depends on all the test + # targets. tests_target = env.Alias("test", tests) AlwaysBuild(tests_target) @@ -347,7 +353,11 @@ env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) # -- Verilator builder verilator_builder = Builder( - action='verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD -Wno-MULTITOP -DNO_ICE40_DEFAULT_ASSIGNMENTS {0} {1} {2} {3} $SOURCES "{4}"'.format( + action=( + "verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD " + "-Wno-MULTITOP -DNO_ICE40_DEFAULT_ASSIGNMENTS {0} {1} {2} {3} " + '$SOURCES "{4}"' + ).format( "-Wall" if VERILATOR_ALL else "", "-Wno-style" if VERILATOR_NO_STYLE else "", VERILATOR_PARAM_STR, diff --git a/tox.ini b/tox.ini index ad141350..dfce1fc4 100644 --- a/tox.ini +++ b/tox.ini @@ -49,12 +49,18 @@ deps = pytest==8.3.3 setenv= - LINT_DIRS = apio test test-boards + LINT_ITEMS = \ + apio \ + test \ + test-boards + ; apio/resources/ice40/SConstruct \ + ; apio/resources/ecp5/SConstruct \ + ; apio/resources/gowin/SConstruct commands = - black {env:LINT_DIRS} - flake8 {env:LINT_DIRS} - pylint {env:LINT_DIRS} + black {env:LINT_ITEMS} + flake8 {env:LINT_ITEMS} + pylint {env:LINT_ITEMS} # ---------------------------------------------------- From ab7b1f42458362bf54878ac1eb2fa69057d3982c Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 28 Sep 2024 11:33:01 -0700 Subject: [PATCH 2/8] Fixed more SConstruct lint errors: apio/resources/ecp5/SConstruct:115:12: F523 '...'.format(...) has unused arguments at position(s): 1 apio/resources/gowin/SConstruct:112:12: F523 '...'.format(...) has unused arguments at position(s): 1, 2 --- apio/resources/ecp5/SConstruct | 5 ++--- apio/resources/gowin/SConstruct | 6 ++---- tox.ini | 6 +++--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/apio/resources/ecp5/SConstruct b/apio/resources/ecp5/SConstruct index 2d17411a..85ce58cc 100644 --- a/apio/resources/ecp5/SConstruct +++ b/apio/resources/ecp5/SConstruct @@ -113,11 +113,10 @@ env.Append(BUILDERS={"Synth": synth_builder}) # -- Place and route Builder. pnr_builder = Builder( action=( - "nextpnr-ecp5 --{0} --package {2} --json $SOURCE --textcfg $TARGET " - "--lpf {3} {4} --timing-allow-fail --force" + "nextpnr-ecp5 --{0} --package {1} --json $SOURCE --textcfg $TARGET " + "--lpf {2} {3} --timing-allow-fail --force" ).format( FPGA_TYPE_PARAM, - FPGA_SIZE, FPGA_PACK, LPF, "" if VERBOSE_ALL or VERBOSE_PNR else "-q", diff --git a/apio/resources/gowin/SConstruct b/apio/resources/gowin/SConstruct index b3032284..a2dd3256 100644 --- a/apio/resources/gowin/SConstruct +++ b/apio/resources/gowin/SConstruct @@ -111,14 +111,12 @@ env.Append(BUILDERS={"Synth": synth_builder}) pnr_builder = Builder( action=( "nextpnr-himbaechel --device {0} --json $SOURCE --write $TARGET " - "--vopt family={5} --vopt cst={3} {4}" + "--vopt family={1} --vopt cst={2} {3}" ).format( FPGA_MODEL, - FPGA_SIZE, - FPGA_PACK, + FPGA_TYPE, CST, "" if VERBOSE_ALL or VERBOSE_PNR else "-q", - FPGA_TYPE, ), suffix=".pnr.json", src_suffix=".json", diff --git a/tox.ini b/tox.ini index dfce1fc4..1a80330a 100644 --- a/tox.ini +++ b/tox.ini @@ -53,9 +53,9 @@ setenv= apio \ test \ test-boards - ; apio/resources/ice40/SConstruct \ - ; apio/resources/ecp5/SConstruct \ - ; apio/resources/gowin/SConstruct + # apio/resources/ice40/SConstruct \ + # apio/resources/ecp5/SConstruct \ + # apio/resources/gowin/SConstruct commands = black {env:LINT_ITEMS} From 85cd103381513d96c2178bd4979b9be996b4ab42 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 28 Sep 2024 12:49:02 -0700 Subject: [PATCH 3/8] Completed the transition of the SConstruct file to pylint. Remaining errors where fixed and/or supressed and the SConstruct files where added to the 'make lint' target. E0611 and E1101 are due to the magic that scons does when running SConstruct, for example, improting methods and variables implicitly such that pylint is not aware of it. A partial workaround is to refer to them through the env object, for example 'env.GLOB()' instead of 'GLOB()' but it's not clear yet what is the best approach. --- apio/resources/ecp5/SConstruct | 39 ++++++++++++++++++++++++++---- apio/resources/gowin/SConstruct | 42 +++++++++++++++++++++++++++++---- apio/resources/ice40/SConstruct | 39 ++++++++++++++++++++++++++---- tox.ini | 9 +++---- 4 files changed, 112 insertions(+), 17 deletions(-) diff --git a/apio/resources/ecp5/SConstruct b/apio/resources/ecp5/SConstruct index 85ce58cc..491db1c0 100644 --- a/apio/resources/ecp5/SConstruct +++ b/apio/resources/ecp5/SConstruct @@ -1,3 +1,5 @@ +"""Scons script of ECP5 FPGAs.""" + # -*- coding: utf-8 -*- # ---------------------------------------------------------------------- # -- Generic Scons script for Sintesizing hardware on an FPGA and more. @@ -7,7 +9,34 @@ # -- Licence GPLv2 # ---------------------------------------------------------------------- -# pylint: disable=fixme +# W0511: TODO: (fixme) +# pylint: disable=W0511 + +# C0103: Module name doesn't conform to snake_case naming style (invalid-name) +# pylint: disable=C0103 + +# C0209: Formatting could be an f-string (consider-using-f-string) +# pylint: disable=C0209 + +# Similar lines in 2 files +# pylint: disable=R0801 + +# W0613: Unused argument 'xx' (unused-argument) +# pylint: disable=W0613 + +# TODO: Can we fix this? +# E0611: No name in module (no-name-in-module) +# pylint: disable=E0611 + +# TODO: Can we fix this? +# E1101: Instance of 'Base' has no 'X' member (no-member) +# pylint: disable=E1101 + +# TODO: Remove this disable after moving the functions with 'env' argument +# to scons_util.py. +# W0621: Redefining name 'env' from outer scope (redefined-outer-name) +# pylint: disable=W0621 + import os import re @@ -78,8 +107,9 @@ TARGET = "hardware" list_files_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) -def list_files_scan(node, env, path): - contents = node.get_text_contents() +def list_files_scan(file_node, env, path): + """Scan a file for includes.""" + contents = file_node.get_text_contents() includes = list_files_re.findall(contents) return env.File(includes) @@ -340,7 +370,8 @@ if "test" in COMMAND_LINE_TARGETS: # -- Verilator config file builder def verilator_config_func(target, source, env): - with open(target[0].get_path(), "w") as target_file: + """Creates a verilator .vlt config files.""" + with open(target[0].get_path(), "w", encoding="utf-8") as target_file: # NOTE: This config was copied from ICE40. Adjust as needed. target_file.write( "`verilator_config\n" diff --git a/apio/resources/gowin/SConstruct b/apio/resources/gowin/SConstruct index a2dd3256..026b46cf 100644 --- a/apio/resources/gowin/SConstruct +++ b/apio/resources/gowin/SConstruct @@ -1,3 +1,5 @@ +"""Scons script of Gowin FPGAs.""" + # -*- coding: utf-8 -*- # ---------------------------------------------------------------------- # -- Generic Scons script for Sintesizing hardware on an FPGA and more. @@ -7,7 +9,34 @@ # -- Licence GPLv2 # ---------------------------------------------------------------------- -# pylint: disable=fixme +# W0511: TODO: (fixme) +# pylint: disable=W0511 + +# C0103: Module name doesn't conform to snake_case naming style (invalid-name) +# pylint: disable=C0103 + +# C0209: Formatting could be an f-string (consider-using-f-string) +# pylint: disable=C0209 + +# Similar lines in 2 files +# pylint: disable=R0801 + +# W0613: Unused argument 'xx' (unused-argument) +# pylint: disable=W0613 + +# TODO: Can we fix this? +# E0611: No name in module (no-name-in-module) +# pylint: disable=E0611 + +# TODO: Can we fix this? +# E1101: Instance of 'Base' has no 'X' member (no-member) +# pylint: disable=E1101 + +# TODO: Remove this disable after moving the functions with 'env' argument +# to scons_util.py. +# W0621: Redefining name 'env' from outer scope (redefined-outer-name) +# pylint: disable=W0621 + import os import re @@ -73,8 +102,9 @@ TARGET = "hardware" list_files_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) -def list_files_scan(node, env, path): - contents = node.get_text_contents() +def list_files_scan(file_node, env, path): + """Scan a file for includes.""" + contents = file_node.get_text_contents() includes = list_files_re.findall(contents) return env.File(includes) @@ -267,9 +297,10 @@ if "sim" in COMMAND_LINE_TARGETS: # TODO: consider to allow specifying the default testbench # in apio.ini. error( + env, ( "Found {} testbranches, please use the --testbench flag." - ).format(len(list_tb)) + ).format(len(list_tb)), ) for tb in list_tb: print("- {}".format(tb)) @@ -337,7 +368,8 @@ if "test" in COMMAND_LINE_TARGETS: # -- Verilator config file builder def verilator_config_func(target, source, env): - with open(target[0].get_path(), "w") as target_file: + """Creates a verilator .vlt config files.""" + with open(target[0].get_path(), "w", encoding="utf-8") as target_file: # NOTE: This config was copied from ICE40. Adjust as needed. target_file.write( "`verilator_config\n" diff --git a/apio/resources/ice40/SConstruct b/apio/resources/ice40/SConstruct index 6792bc55..2e4eb35d 100644 --- a/apio/resources/ice40/SConstruct +++ b/apio/resources/ice40/SConstruct @@ -1,3 +1,5 @@ +"""Scons script of ICE40 FPGAs.""" + # -*- coding: utf-8 -*- # ---------------------------------------------------------------------- # -- Generic Scons script for Sintesizing hardware on an FPGA and more. @@ -7,7 +9,34 @@ # -- Licence GPLv2 # ---------------------------------------------------------------------- -# pylint: disable=fixme +# W0511: TODO: (fixme) +# pylint: disable=W0511 + +# C0103: Module name doesn't conform to snake_case naming style (invalid-name) +# pylint: disable=C0103 + +# C0209: Formatting could be an f-string (consider-using-f-string) +# pylint: disable=C0209 + +# Similar lines in 2 files +# pylint: disable=R0801 + +# W0613: Unused argument 'xx' (unused-argument) +# pylint: disable=W0613 + +# TODO: Can we fix this? +# E0611: No name in module (no-name-in-module) +# pylint: disable=E0611 + +# TODO: Can we fix this? +# E1101: Instance of 'Base' has no 'X' member (no-member) +# pylint: disable=E1101 + +# TODO: Remove this disable after moving the functions with 'env' argument +# to scons_util.py. +# W0621: Redefining name 'env' from outer scope (redefined-outer-name) +# pylint: disable=W0621 + import os import re @@ -71,8 +100,9 @@ TARGET = "hardware" list_files_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) -def list_files_scan(node, env, path): - contents = node.get_text_contents() +def list_files_scan(file_node, env, path): + """Scan a file for includes.""" + contents = file_node.get_text_contents() includes = list_files_re.findall(contents) return env.File(includes) @@ -335,7 +365,8 @@ if "test" in COMMAND_LINE_TARGETS: # -- Verilator config file builder def verilator_config_func(target, source, env): - with open(target[0].get_path(), "w") as target_file: + """Creates a verilator .vlt config files.""" + with open(target[0].get_path(), "w", encoding="utf-8") as target_file: target_file.write( "`verilator_config\n" f'lint_off -rule COMBDLY -file "{YOSYS_CELLS_PATH}"\n' diff --git a/tox.ini b/tox.ini index 1a80330a..aff40b99 100644 --- a/tox.ini +++ b/tox.ini @@ -49,13 +49,14 @@ deps = pytest==8.3.3 setenv= + # TODO: Can we avoid specifying explicitly each SConstruct? LINT_ITEMS = \ apio \ test \ - test-boards - # apio/resources/ice40/SConstruct \ - # apio/resources/ecp5/SConstruct \ - # apio/resources/gowin/SConstruct + test-boards \ + apio/resources/ice40/SConstruct \ + apio/resources/ecp5/SConstruct \ + apio/resources/gowin/SConstruct commands = black {env:LINT_ITEMS} From c8103c7ff7e539aeb9abbb7ceedc07fe3b3b9134 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 28 Sep 2024 15:34:38 -0700 Subject: [PATCH 4/8] Refactored the list scanner functionality from the SConstruct files to the common scons_util.py library. Behavior should be identical. --- apio/resources/ecp5/SConstruct | 28 ++++++++++------------------ apio/resources/gowin/SConstruct | 27 ++++++++++----------------- apio/resources/ice40/SConstruct | 28 ++++++++++------------------ apio/scons_util.py | 31 ++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 54 deletions(-) diff --git a/apio/resources/ecp5/SConstruct b/apio/resources/ecp5/SConstruct index 491db1c0..78e0172a 100644 --- a/apio/resources/ecp5/SConstruct +++ b/apio/resources/ecp5/SConstruct @@ -39,7 +39,6 @@ import os -import re from platform import system from SCons.Script import ( Builder, @@ -61,6 +60,7 @@ from apio.scons_util import ( arg_str, get_verilator_param_str, get_programmer_cmd, + make_icestudio_list_scanner, ) # -- Create the environment @@ -103,19 +103,11 @@ FPGA_TYPE_PARAM = "25k" if (FPGA_TYPE == "12k") else "{0}".format(FPGA_TYPE) # -- Target name TARGET = "hardware" -# -- Scan required .list files -list_files_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) +# -- Create a .v file scanner for icestudio embedded references to *.list +# -- files. +icestudio_list_scanner = make_icestudio_list_scanner(env) -def list_files_scan(file_node, env, path): - """Scan a file for includes.""" - contents = file_node.get_text_contents() - includes = list_files_re.findall(contents) - return env.File(includes) - - -list_scanner = env.Scanner(function=list_files_scan) - # -- Get a list of all the verilog files in the src folfer, in ASCII, with # -- the full path. All these files are used for the simulation v_nodes = Glob("*.v") @@ -136,7 +128,7 @@ synth_builder = Builder( ), suffix=".json", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"Synth": synth_builder}) @@ -236,7 +228,7 @@ iverilog_builder = Builder( generator=iverilog_generator, suffix=".out", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"IVerilog": iverilog_builder}) @@ -251,7 +243,7 @@ dot_builder = Builder( ), suffix=".dot", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"DOT": dot_builder}) @@ -260,7 +252,7 @@ svg_builder = Builder( action="dot -Tsvg $SOURCES -o $TARGET", suffix=".svg", src_suffix=".dot", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"SVG": svg_builder}) @@ -384,7 +376,7 @@ def verilator_config_func(target, source, env): verilator_config_builder = Builder( action=Action(verilator_config_func, "Creating verilator config file."), suffix=".vlt", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) @@ -401,7 +393,7 @@ verilator_builder = Builder( YOSYS_CELLS_PATH, ), src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"Verilator": verilator_builder}) diff --git a/apio/resources/gowin/SConstruct b/apio/resources/gowin/SConstruct index 026b46cf..f78ca20c 100644 --- a/apio/resources/gowin/SConstruct +++ b/apio/resources/gowin/SConstruct @@ -39,7 +39,6 @@ import os -import re from platform import system from SCons.Script import ( Builder, @@ -61,6 +60,7 @@ from apio.scons_util import ( arg_str, get_verilator_param_str, get_programmer_cmd, + make_icestudio_list_scanner, ) # -- Create the environment @@ -98,18 +98,11 @@ IVER_PATH = "" if isWindows or not IVL_PATH else '-B "{0}"'.format(IVL_PATH) # -- Target name TARGET = "hardware" -# -- Scan required .list files -list_files_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) +# -- Create a .v file scanner for icestudio embedded references to *.list +# -- files. +icestudio_list_scanner = make_icestudio_list_scanner(env) -def list_files_scan(file_node, env, path): - """Scan a file for includes.""" - contents = file_node.get_text_contents() - includes = list_files_re.findall(contents) - return env.File(includes) - - -list_scanner = env.Scanner(function=list_files_scan) # -- Get a list of all the verilog files in the src folfer, in ASCII, with # -- the full path. All these files are used for the simulation @@ -133,7 +126,7 @@ synth_builder = Builder( ), suffix=".json", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"Synth": synth_builder}) @@ -234,7 +227,7 @@ iverilog_builder = Builder( generator=iverilog_generator, suffix=".out", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"IVerilog": iverilog_builder}) @@ -248,7 +241,7 @@ dot_builder = Builder( ), suffix=".dot", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"DOT": dot_builder}) @@ -257,7 +250,7 @@ svg_builder = Builder( action="dot -Tsvg $SOURCES -o $TARGET", suffix=".svg", src_suffix=".dot", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"SVG": svg_builder}) @@ -382,7 +375,7 @@ def verilator_config_func(target, source, env): verilator_config_builder = Builder( action=Action(verilator_config_func, "Creating verilator config file."), suffix=".vlt", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) @@ -399,7 +392,7 @@ verilator_builder = Builder( YOSYS_CELLS_PATH, ), src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"Verilator": verilator_builder}) diff --git a/apio/resources/ice40/SConstruct b/apio/resources/ice40/SConstruct index 2e4eb35d..84e810d2 100644 --- a/apio/resources/ice40/SConstruct +++ b/apio/resources/ice40/SConstruct @@ -39,7 +39,6 @@ import os -import re from platform import system from SCons.Script import ( Builder, @@ -61,6 +60,7 @@ from apio.scons_util import ( arg_str, get_verilator_param_str, get_programmer_cmd, + make_icestudio_list_scanner, ) # -- Create the environment @@ -96,18 +96,10 @@ IVER_PATH = "" if isWindows or not IVL_PATH else '-B "{0}"'.format(IVL_PATH) # -- Target name TARGET = "hardware" -# -- Scan required .list files -list_files_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) - -def list_files_scan(file_node, env, path): - """Scan a file for includes.""" - contents = file_node.get_text_contents() - includes = list_files_re.findall(contents) - return env.File(includes) - - -list_scanner = env.Scanner(function=list_files_scan) +# -- Create a .v file scanner for icestudio embedded references to *.list +# -- files. +icestudio_list_scanner = make_icestudio_list_scanner(env) # -- Get a list of all the verilog files in the src folfer, in ASCII, with # -- the full path. All these files are used for the simulation @@ -129,7 +121,7 @@ synth_builder = Builder( ), suffix=".json", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"Synth": synth_builder}) @@ -231,7 +223,7 @@ iverilog_builder = Builder( generator=iverilog_generator, suffix=".out", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"IVerilog": iverilog_builder}) @@ -245,7 +237,7 @@ dot_builder = Builder( ), suffix=".dot", src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"DOT": dot_builder}) @@ -254,7 +246,7 @@ svg_builder = Builder( action="dot -Tsvg $SOURCES -o $TARGET", suffix=".svg", src_suffix=".dot", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"SVG": svg_builder}) @@ -378,7 +370,7 @@ def verilator_config_func(target, source, env): verilator_config_builder = Builder( action=Action(verilator_config_func, "Creating verilator config file."), suffix=".vlt", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) @@ -396,7 +388,7 @@ verilator_builder = Builder( YOSYS_CELLS_PATH, ), src_suffix=".v", - source_scanner=list_scanner, + source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"Verilator": verilator_builder}) diff --git a/apio/scons_util.py b/apio/scons_util.py index ea880a9e..b853cf5a 100644 --- a/apio/scons_util.py +++ b/apio/scons_util.py @@ -17,9 +17,12 @@ # pylint: disable=unused-argument import os -from typing import Dict +import re +from typing import Dict, List +import SCons from SCons.Script import DefaultEnvironment from SCons.Script.SConscript import SConsEnvironment +import SCons.Node.FS import click @@ -212,3 +215,29 @@ def get_programmer_cmd(env: SConsEnvironment) -> str: prog_cmd = prog_arg.replace("${SOURCE}", "$SOURCE") return prog_cmd + + +def make_icestudio_list_scanner(env: SConsEnvironment) -> SCons.Scanner: + """Creates a scons file scanner for IceStudio embedded *.list file + references + """ + # A Regex to match reference to .list files in icestudio auto generated + # .v files. + # Example: + # Line: ' parameter v771499 = "v771499.list"' + # Match: 'v771499.list' + icestudio_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) + + def icestudio_scanner( + file_node: SCons.Node.FS.File, env: SConsEnvironment, ignored_path + ) -> List[str]: + """Scan a source file for references to IceStudio *.list proprietry + files.""" + text = file_node.get_text_contents() + # E.g. ['v771499.list', 'v9298ae.list', 'vba98fe.list'] + includes = icestudio_re.findall(text) + # For debugging. + # print(f"Icestudio refs: {file_node.name} -> {includes}") + return env.File(includes) + + return env.Scanner(function=icestudio_scanner) From 389db801cdca2995c6076e8b61d61638c675994e Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 28 Sep 2024 17:03:01 -0700 Subject: [PATCH 5/8] Repurpused the list scanner as a general verilog source scanner that identifies also verilog import directives. --- apio/resources/ecp5/SConstruct | 18 ++++------ apio/resources/gowin/SConstruct | 18 ++++------ apio/resources/ice40/SConstruct | 18 ++++------ apio/scons_util.py | 62 ++++++++++++++++++++++----------- 4 files changed, 62 insertions(+), 54 deletions(-) diff --git a/apio/resources/ecp5/SConstruct b/apio/resources/ecp5/SConstruct index 78e0172a..ce9da82f 100644 --- a/apio/resources/ecp5/SConstruct +++ b/apio/resources/ecp5/SConstruct @@ -60,7 +60,7 @@ from apio.scons_util import ( arg_str, get_verilator_param_str, get_programmer_cmd, - make_icestudio_list_scanner, + make_verilog_src_scanner, ) # -- Create the environment @@ -103,10 +103,8 @@ FPGA_TYPE_PARAM = "25k" if (FPGA_TYPE == "12k") else "{0}".format(FPGA_TYPE) # -- Target name TARGET = "hardware" -# -- Create a .v file scanner for icestudio embedded references to *.list -# -- files. -icestudio_list_scanner = make_icestudio_list_scanner(env) - +# -- Create scannenr to identify dependencies in verilog files. +verilog_src_scanner = make_verilog_src_scanner(env) # -- Get a list of all the verilog files in the src folfer, in ASCII, with # -- the full path. All these files are used for the simulation @@ -128,7 +126,7 @@ synth_builder = Builder( ), suffix=".json", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"Synth": synth_builder}) @@ -228,7 +226,7 @@ iverilog_builder = Builder( generator=iverilog_generator, suffix=".out", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"IVerilog": iverilog_builder}) @@ -243,7 +241,7 @@ dot_builder = Builder( ), suffix=".dot", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"DOT": dot_builder}) @@ -252,7 +250,6 @@ svg_builder = Builder( action="dot -Tsvg $SOURCES -o $TARGET", suffix=".svg", src_suffix=".dot", - source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"SVG": svg_builder}) @@ -376,7 +373,6 @@ def verilator_config_func(target, source, env): verilator_config_builder = Builder( action=Action(verilator_config_func, "Creating verilator config file."), suffix=".vlt", - source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) @@ -393,7 +389,7 @@ verilator_builder = Builder( YOSYS_CELLS_PATH, ), src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"Verilator": verilator_builder}) diff --git a/apio/resources/gowin/SConstruct b/apio/resources/gowin/SConstruct index f78ca20c..83356367 100644 --- a/apio/resources/gowin/SConstruct +++ b/apio/resources/gowin/SConstruct @@ -60,7 +60,7 @@ from apio.scons_util import ( arg_str, get_verilator_param_str, get_programmer_cmd, - make_icestudio_list_scanner, + make_verilog_src_scanner, ) # -- Create the environment @@ -98,11 +98,8 @@ IVER_PATH = "" if isWindows or not IVL_PATH else '-B "{0}"'.format(IVL_PATH) # -- Target name TARGET = "hardware" - -# -- Create a .v file scanner for icestudio embedded references to *.list -# -- files. -icestudio_list_scanner = make_icestudio_list_scanner(env) - +# -- Create scannenr to identify dependencies in verilog files. +verilog_src_scanner = make_verilog_src_scanner(env) # -- Get a list of all the verilog files in the src folfer, in ASCII, with # -- the full path. All these files are used for the simulation @@ -126,7 +123,7 @@ synth_builder = Builder( ), suffix=".json", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"Synth": synth_builder}) @@ -227,7 +224,7 @@ iverilog_builder = Builder( generator=iverilog_generator, suffix=".out", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"IVerilog": iverilog_builder}) @@ -241,7 +238,7 @@ dot_builder = Builder( ), suffix=".dot", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"DOT": dot_builder}) @@ -250,7 +247,6 @@ svg_builder = Builder( action="dot -Tsvg $SOURCES -o $TARGET", suffix=".svg", src_suffix=".dot", - source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"SVG": svg_builder}) @@ -375,7 +371,6 @@ def verilator_config_func(target, source, env): verilator_config_builder = Builder( action=Action(verilator_config_func, "Creating verilator config file."), suffix=".vlt", - source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) @@ -392,7 +387,6 @@ verilator_builder = Builder( YOSYS_CELLS_PATH, ), src_suffix=".v", - source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"Verilator": verilator_builder}) diff --git a/apio/resources/ice40/SConstruct b/apio/resources/ice40/SConstruct index 84e810d2..3fdbbfdb 100644 --- a/apio/resources/ice40/SConstruct +++ b/apio/resources/ice40/SConstruct @@ -60,7 +60,7 @@ from apio.scons_util import ( arg_str, get_verilator_param_str, get_programmer_cmd, - make_icestudio_list_scanner, + make_verilog_src_scanner, ) # -- Create the environment @@ -96,10 +96,8 @@ IVER_PATH = "" if isWindows or not IVL_PATH else '-B "{0}"'.format(IVL_PATH) # -- Target name TARGET = "hardware" - -# -- Create a .v file scanner for icestudio embedded references to *.list -# -- files. -icestudio_list_scanner = make_icestudio_list_scanner(env) +# -- Create scannenr to identify dependencies in verilog files. +verilog_src_scanner = make_verilog_src_scanner(env) # -- Get a list of all the verilog files in the src folfer, in ASCII, with # -- the full path. All these files are used for the simulation @@ -121,7 +119,7 @@ synth_builder = Builder( ), suffix=".json", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"Synth": synth_builder}) @@ -223,7 +221,7 @@ iverilog_builder = Builder( generator=iverilog_generator, suffix=".out", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"IVerilog": iverilog_builder}) @@ -237,7 +235,7 @@ dot_builder = Builder( ), suffix=".dot", src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"DOT": dot_builder}) @@ -246,7 +244,6 @@ svg_builder = Builder( action="dot -Tsvg $SOURCES -o $TARGET", suffix=".svg", src_suffix=".dot", - source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"SVG": svg_builder}) @@ -370,7 +367,6 @@ def verilator_config_func(target, source, env): verilator_config_builder = Builder( action=Action(verilator_config_func, "Creating verilator config file."), suffix=".vlt", - source_scanner=icestudio_list_scanner, ) env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) @@ -388,7 +384,7 @@ verilator_builder = Builder( YOSYS_CELLS_PATH, ), src_suffix=".v", - source_scanner=icestudio_list_scanner, + source_scanner=verilog_src_scanner, ) env.Append(BUILDERS={"Verilator": verilator_builder}) diff --git a/apio/scons_util.py b/apio/scons_util.py index b853cf5a..833a4019 100644 --- a/apio/scons_util.py +++ b/apio/scons_util.py @@ -217,27 +217,49 @@ def get_programmer_cmd(env: SConsEnvironment) -> str: return prog_cmd -def make_icestudio_list_scanner(env: SConsEnvironment) -> SCons.Scanner: - """Creates a scons file scanner for IceStudio embedded *.list file - references +def make_verilog_src_scanner(env: SConsEnvironment) -> SCons.Scanner: + """Creates and returns a scons Scanner object for scanning verilog + files for dependencies. """ - # A Regex to match reference to .list files in icestudio auto generated - # .v files. + # A Regex to icestudio propriaetry references for *.list files. # Example: - # Line: ' parameter v771499 = "v771499.list"' - # Match: 'v771499.list' - icestudio_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) - - def icestudio_scanner( + # Text: ' parameter v771499 = "v771499.list"' + # Captures: 'v771499.list' + icestudio_list_re = re.compile(r"[\n|\s][^\/]?\"(.*\.list?)\"", re.M) + + # A regex to match a verilog include. + # Example + # Text: `include "apio_testing.vh" + # Capture: 'apio_testing.vh' + verilog_include_re = re.compile( + r'`\s*include\s+["]([a-zA-Z_./]+)["]', re.M + ) + + def verilog_src_scanner_func( file_node: SCons.Node.FS.File, env: SConsEnvironment, ignored_path ) -> List[str]: - """Scan a source file for references to IceStudio *.list proprietry - files.""" - text = file_node.get_text_contents() - # E.g. ['v771499.list', 'v9298ae.list', 'vba98fe.list'] - includes = icestudio_re.findall(text) - # For debugging. - # print(f"Icestudio refs: {file_node.name} -> {includes}") - return env.File(includes) - - return env.Scanner(function=icestudio_scanner) + """Given a Verilog file, scan it and return a list of references + to other files it depends on. It's not require to report dependency + on another .v file in the project since scons loads anyway + all the .v files in the project. + + Returns a list of files. + """ + # Sanity check. Should be called only to scan verilog files. + assert file_node.name.lower().endswith(".v"), file_node.name + includes_set = set() + file_text = file_node.get_text_contents() + # Get IceStudio includes. + includes = icestudio_list_re.findall(file_text) + includes_set.update(includes) + # Get Standard verilog includes. + includes = verilog_include_re.findall(file_text) + includes_set.update(includes) + # Get a deterministic list. + includes_list = sorted(list(includes_set)) + # For sanity check. Remove if too noisy. + if includes_list: + info(env, f"{file_node.name} includes {', '.join(includes_list)}.") + return env.File(includes_list) + + return env.Scanner(function=verilog_src_scanner_func) From d37f68092944fc6ba186055d6fa80140db05562e Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 28 Sep 2024 19:08:39 -0700 Subject: [PATCH 6/8] Minor clean up of the build target names. Also, made the AlwaysBuild attribure of he build target conditional on verbose all. An no change apio build now gives a nice "scons: `build' is up to date." message. --- apio/resources/ecp5/SConstruct | 27 ++++++++++++++++----------- apio/resources/gowin/SConstruct | 28 ++++++++++++++-------------- apio/resources/ice40/SConstruct | 28 ++++++++++++++-------------- 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/apio/resources/ecp5/SConstruct b/apio/resources/ecp5/SConstruct index ce9da82f..e7db9a53 100644 --- a/apio/resources/ecp5/SConstruct +++ b/apio/resources/ecp5/SConstruct @@ -168,20 +168,25 @@ time_rpt_builder = Builder( env.Append(BUILDERS={"Time": time_rpt_builder}) # -- Generate the bitstream -json_out_target = env.Synth(TARGET, [src_synth]) -config_out_target = env.PnR(TARGET, [json_out_target, LPF]) -bitstream_target = env.Bin(TARGET, config_out_target) - -build_target = env.Alias("build", bitstream_target) -AlwaysBuild(build_target) +synth_target = env.Synth(TARGET, [src_synth]) +pnr_target = env.PnR(TARGET, [synth_target, LPF]) +bin_target = env.Bin(TARGET, pnr_target) +build_target = env.Alias("build", bin_target) + +if VERBOSE_YOSYS: + AlwaysBuild(synth_target) +if VERBOSE_PNR: + AlwaysBuild(pnr_target) +if VERBOSE_ALL: + AlwaysBuild(synth_target, pnr_target, build_target) # -- Upload the bitstream into FPGA programmer_cmd = get_programmer_cmd(env) -upload_target = env.Alias("upload", bitstream_target, programmer_cmd) +upload_target = env.Alias("upload", bin_target, programmer_cmd) AlwaysBuild(upload_target) # -- Target time: calculate the time -time_rpt_target = env.Time(config_out_target) +time_rpt_target = env.Time(pnr_target) AlwaysBuild(time_rpt_target) time_target = env.Alias("time", time_rpt_target) @@ -401,7 +406,7 @@ lint_out_target = env.Verilator( lint_target = env.Alias("lint", lint_out_target) AlwaysBuild(lint_target) -Default(bitstream_target) +Default(bin_target) # -- These is for cleaning the artifact files. if GetOption("clean"): @@ -417,8 +422,8 @@ if GetOption("clean"): [ time_target, build_target, - json_out_target, - config_out_target, + synth_target, + pnr_target, graph_target, lint_target, ] diff --git a/apio/resources/gowin/SConstruct b/apio/resources/gowin/SConstruct index 83356367..0993a6ea 100644 --- a/apio/resources/gowin/SConstruct +++ b/apio/resources/gowin/SConstruct @@ -164,25 +164,25 @@ time_rpt_builder = Builder( env.Append(BUILDERS={"Time": time_rpt_builder}) # -- Generate the bitstream -blif_target = env.Synth(TARGET, [src_synth]) -asc_target = env.PnR(TARGET, [blif_target, CST]) -bitstream_target = env.Bin(TARGET, asc_target) - -build_target = env.Alias("build", bitstream_target) -AlwaysBuild(build_target) - -if VERBOSE_ALL or VERBOSE_YOSYS: - AlwaysBuild(blif_target) -if VERBOSE_ALL or VERBOSE_PNR: - AlwaysBuild(asc_target) +synth_target = env.Synth(TARGET, [src_synth]) +pnr_target = env.PnR(TARGET, [synth_target, CST]) +bin_target = env.Bin(TARGET, pnr_target) +build_target = env.Alias("build", bin_target) + +if VERBOSE_YOSYS: + AlwaysBuild(synth_target) +if VERBOSE_PNR: + AlwaysBuild(pnr_target) +if VERBOSE_ALL: + AlwaysBuild(synth_target, pnr_target, build_target) # -- Upload the bitstream into FPGA programmer_cmd = get_programmer_cmd(env) -upload_target = env.Alias("upload", bitstream_target, programmer_cmd) +upload_target = env.Alias("upload", bin_target, programmer_cmd) AlwaysBuild(upload_target) # -- Target time: calculate the time -rpt_target = env.Time(asc_target) +rpt_target = env.Time(pnr_target) AlwaysBuild(rpt_target) time_target = env.Alias("time", rpt_target) @@ -398,7 +398,7 @@ lint_out_target = env.Verilator( lint_target = env.Alias("lint", lint_out_target) AlwaysBuild(lint_target) -Default(bitstream_target) +Default(bin_target) # -- These is for cleaning the artifact files. if GetOption("clean"): diff --git a/apio/resources/ice40/SConstruct b/apio/resources/ice40/SConstruct index 3fdbbfdb..7014b7ea 100644 --- a/apio/resources/ice40/SConstruct +++ b/apio/resources/ice40/SConstruct @@ -158,25 +158,25 @@ time_rpt_builder = Builder( env.Append(BUILDERS={"Time": time_rpt_builder}) # -- Generate the bitstream -blif_target = env.Synth(TARGET, [src_synth]) -asc_target = env.PnR(TARGET, [blif_target, PCF]) -bitstream_target = env.Bin(TARGET, asc_target) - -build_target = env.Alias("build", bitstream_target) -AlwaysBuild(build_target) - -if VERBOSE_ALL or VERBOSE_YOSYS: - AlwaysBuild(blif_target) -if VERBOSE_ALL or VERBOSE_PNR: - AlwaysBuild(asc_target) +synth_target = env.Synth(TARGET, [src_synth]) +pnr_target = env.PnR(TARGET, [synth_target, PCF]) +bin_target = env.Bin(TARGET, pnr_target) +build_target = env.Alias("build", bin_target) + +if VERBOSE_YOSYS: + AlwaysBuild(synth_target) +if VERBOSE_PNR: + AlwaysBuild(pnr_target) +if VERBOSE_ALL: + AlwaysBuild(synth_target, pnr_target, build_target) # -- Upload the bitstream into FPGA programmer_cmd = get_programmer_cmd(env) -upload_target = env.Alias("upload", bitstream_target, programmer_cmd) +upload_target = env.Alias("upload", bin_target, programmer_cmd) AlwaysBuild(upload_target) # -- Target time: calculate the time -rpt_target = env.Time(asc_target) +rpt_target = env.Time(pnr_target) AlwaysBuild(rpt_target) time_target = env.Alias("time", rpt_target) @@ -396,7 +396,7 @@ lint_out_target = env.Verilator( lint_target = env.Alias("lint", lint_out_target) AlwaysBuild(lint_target) -Default(bitstream_target) +Default(bin_target) # -- These is for cleaning the artifact files. if GetOption("clean"): From d7f91c7884680b6e97c0a17a8460357cef79f57d Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 28 Sep 2024 20:40:39 -0700 Subject: [PATCH 7/8] Fixed an issue with the verilator targets dependency that caused the verilator config file hardware.vlt to be sent to the verilog source scanner. --- apio/resources/ecp5/SConstruct | 10 ++++------ apio/resources/gowin/SConstruct | 10 ++++------ apio/resources/ice40/SConstruct | 10 ++++------ apio/scons_util.py | 9 +++++---- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/apio/resources/ecp5/SConstruct b/apio/resources/ecp5/SConstruct index e7db9a53..bc6e277a 100644 --- a/apio/resources/ecp5/SConstruct +++ b/apio/resources/ecp5/SConstruct @@ -43,7 +43,6 @@ from platform import system from SCons.Script import ( Builder, Action, - Default, AlwaysBuild, GetOption, Exit, @@ -385,12 +384,13 @@ env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) verilator_builder = Builder( action=( "verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD " - '-Wno-MULTITOP {0} {1} {2} {3} $SOURCES "{4}"' + '-Wno-MULTITOP {0} {1} {2} {3} {4} $SOURCES "{5}"' ).format( "-Wall" if VERILATOR_ALL else "", "-Wno-style" if VERILATOR_NO_STYLE else "", VERILATOR_PARAM_STR, "--top-module " + TOP_MODULE if TOP_MODULE else "", + TARGET + ".vlt", YOSYS_CELLS_PATH, ), src_suffix=".v", @@ -400,13 +400,11 @@ env.Append(BUILDERS={"Verilator": verilator_builder}) # --- Lint lint_config_target = env.VerilatorConfig(TARGET, []) -lint_out_target = env.Verilator( - TARGET, [TARGET + ".vlt"] + src_synth + list_tb -) +lint_out_target = env.Verilator(TARGET, src_synth + list_tb) +env.Depends(lint_out_target, lint_config_target) lint_target = env.Alias("lint", lint_out_target) AlwaysBuild(lint_target) -Default(bin_target) # -- These is for cleaning the artifact files. if GetOption("clean"): diff --git a/apio/resources/gowin/SConstruct b/apio/resources/gowin/SConstruct index 0993a6ea..be63d073 100644 --- a/apio/resources/gowin/SConstruct +++ b/apio/resources/gowin/SConstruct @@ -43,7 +43,6 @@ from platform import system from SCons.Script import ( Builder, Action, - Default, AlwaysBuild, GetOption, Exit, @@ -378,12 +377,13 @@ env.Append(BUILDERS={"VerilatorConfig": verilator_config_builder}) verilator_builder = Builder( action=( "verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD " - '-Wno-MULTITOP {0} {1} {2} {3} $SOURCES "{4}"' + '-Wno-MULTITOP {0} {1} {2} {3} {4} $SOURCES "{5}"' ).format( "-Wall" if VERILATOR_ALL else "", "-Wno-style" if VERILATOR_NO_STYLE else "", VERILATOR_PARAM_STR, "--top-module " + TOP_MODULE if TOP_MODULE else "", + TARGET + ".vlt", YOSYS_CELLS_PATH, ), src_suffix=".v", @@ -392,13 +392,11 @@ env.Append(BUILDERS={"Verilator": verilator_builder}) # --- Lint lint_config_target = env.VerilatorConfig(TARGET, []) -lint_out_target = env.Verilator( - TARGET, [TARGET + ".vlt"] + src_synth + list_tb -) +lint_out_target = env.Verilator(TARGET, src_synth + list_tb) +env.Depends(lint_out_target, lint_config_target) lint_target = env.Alias("lint", lint_out_target) AlwaysBuild(lint_target) -Default(bin_target) # -- These is for cleaning the artifact files. if GetOption("clean"): diff --git a/apio/resources/ice40/SConstruct b/apio/resources/ice40/SConstruct index 7014b7ea..3831d868 100644 --- a/apio/resources/ice40/SConstruct +++ b/apio/resources/ice40/SConstruct @@ -43,7 +43,6 @@ from platform import system from SCons.Script import ( Builder, Action, - Default, AlwaysBuild, GetOption, Exit, @@ -375,12 +374,13 @@ verilator_builder = Builder( action=( "verilator --lint-only --bbox-unsup --timing -Wno-TIMESCALEMOD " "-Wno-MULTITOP -DNO_ICE40_DEFAULT_ASSIGNMENTS {0} {1} {2} {3} " - '$SOURCES "{4}"' + '{4} $SOURCES "{5}"' ).format( "-Wall" if VERILATOR_ALL else "", "-Wno-style" if VERILATOR_NO_STYLE else "", VERILATOR_PARAM_STR, "--top-module " + TOP_MODULE if TOP_MODULE else "", + TARGET + ".vlt", YOSYS_CELLS_PATH, ), src_suffix=".v", @@ -390,13 +390,11 @@ env.Append(BUILDERS={"Verilator": verilator_builder}) # --- Lint lint_config_target = env.VerilatorConfig(TARGET, []) -lint_out_target = env.Verilator( - TARGET, [TARGET + ".vlt"] + src_synth + list_tb -) +lint_out_target = env.Verilator(TARGET, src_synth + list_tb) +env.Depends(lint_out_target, lint_config_target) lint_target = env.Alias("lint", lint_out_target) AlwaysBuild(lint_target) -Default(bin_target) # -- These is for cleaning the artifact files. if GetOption("clean"): diff --git a/apio/scons_util.py b/apio/scons_util.py index 833a4019..0e50d5fd 100644 --- a/apio/scons_util.py +++ b/apio/scons_util.py @@ -246,7 +246,9 @@ def verilog_src_scanner_func( Returns a list of files. """ # Sanity check. Should be called only to scan verilog files. - assert file_node.name.lower().endswith(".v"), file_node.name + assert file_node.name.lower().endswith( + ".v" + ), f"Not a .v file: {file_node.name}" includes_set = set() file_text = file_node.get_text_contents() # Get IceStudio includes. @@ -257,9 +259,8 @@ def verilog_src_scanner_func( includes_set.update(includes) # Get a deterministic list. includes_list = sorted(list(includes_set)) - # For sanity check. Remove if too noisy. - if includes_list: - info(env, f"{file_node.name} includes {', '.join(includes_list)}.") + # For debugging + # info(env, f"*** {file_node.name} includes {includes_list}") return env.File(includes_list) return env.Scanner(function=verilog_src_scanner_func) From 5f92c9abc1df39a0dd530c148efe9713aef0e057 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 28 Sep 2024 21:40:38 -0700 Subject: [PATCH 8/8] Added to test-examples a the ECP5 example ColorLight-5A-75B-V8/Blinky for testing. This is a straight verilog project but can replaced later with a IceStudion version. --- .../ColorLight-5A-75B-V8/Blinky/Blinky.v | 17 +++++++++++++++++ .../ColorLight-5A-75B-V8/Blinky/apio.ini | 4 ++++ test-examples/ColorLight-5A-75B-V8/Blinky/info | 1 + .../ColorLight-5A-75B-V8/Blinky/pinout.lpf | 12 ++++++++++++ 4 files changed, 34 insertions(+) create mode 100644 test-examples/ColorLight-5A-75B-V8/Blinky/Blinky.v create mode 100644 test-examples/ColorLight-5A-75B-V8/Blinky/apio.ini create mode 100644 test-examples/ColorLight-5A-75B-V8/Blinky/info create mode 100644 test-examples/ColorLight-5A-75B-V8/Blinky/pinout.lpf diff --git a/test-examples/ColorLight-5A-75B-V8/Blinky/Blinky.v b/test-examples/ColorLight-5A-75B-V8/Blinky/Blinky.v new file mode 100644 index 00000000..f662a47e --- /dev/null +++ b/test-examples/ColorLight-5A-75B-V8/Blinky/Blinky.v @@ -0,0 +1,17 @@ +//------------------------------------------------------------------ +//-- Blinking LED +//------------------------------------------------------------------ + +module Test ( + input CLK, // 25MHz clock + output led, // LED to blink +); + + reg [23:0] counter = 0; + + always @(posedge CLK) + counter <= counter + 1; + + assign led = counter[23]; + +endmodule diff --git a/test-examples/ColorLight-5A-75B-V8/Blinky/apio.ini b/test-examples/ColorLight-5A-75B-V8/Blinky/apio.ini new file mode 100644 index 00000000..0a4a03e7 --- /dev/null +++ b/test-examples/ColorLight-5A-75B-V8/Blinky/apio.ini @@ -0,0 +1,4 @@ +[env] +board = ColorLight-5A-75B-V8 +top-module = Test + diff --git a/test-examples/ColorLight-5A-75B-V8/Blinky/info b/test-examples/ColorLight-5A-75B-V8/Blinky/info new file mode 100644 index 00000000..f4dd032a --- /dev/null +++ b/test-examples/ColorLight-5A-75B-V8/Blinky/info @@ -0,0 +1 @@ +Blinking LED diff --git a/test-examples/ColorLight-5A-75B-V8/Blinky/pinout.lpf b/test-examples/ColorLight-5A-75B-V8/Blinky/pinout.lpf new file mode 100644 index 00000000..daeba267 --- /dev/null +++ b/test-examples/ColorLight-5A-75B-V8/Blinky/pinout.lpf @@ -0,0 +1,12 @@ +# -- Board: ColorLight-5A-75E-V71_(FT2232H) + +# -- CLK +LOCATE COMP "CLK" SITE "P6"; +IOBUF PORT "CLK" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; + +# -- LED +LOCATE COMP "led" SITE "T6"; +IOBUF PORT "led" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; + + +