From fd61e4d3db0ec4d69ff73c788674695d8af9752a Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Tue, 23 Jul 2024 18:18:19 +0200 Subject: [PATCH 01/15] Added gatemate vendor and Updated init file --- amaranth/vendor/__init__.py | 4 ++ amaranth/vendor/_gatemate.py | 120 +++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) mode change 100644 => 100755 amaranth/vendor/__init__.py create mode 100755 amaranth/vendor/_gatemate.py diff --git a/amaranth/vendor/__init__.py b/amaranth/vendor/__init__.py old mode 100644 new mode 100755 index c60bb4d0d..726020b76 --- a/amaranth/vendor/__init__.py +++ b/amaranth/vendor/__init__.py @@ -6,6 +6,7 @@ __all__ = [ "AlteraPlatform", "AMDPlatform", + "GateMatePlatform" "GowinPlatform", "IntelPlatform", "LatticeECP5Platform", @@ -30,6 +31,9 @@ def __getattr__(name): if name == "GowinPlatform": from ._gowin import GowinPlatform return GowinPlatform + if name == "GateMatePlatform": + from ._gatemate import GateMatePlatform + return GateMatePlatform if name in ("LatticePlatform", "LatticeECP5Platform", "LatticeMachXO2Platform", "LatticeMachXO3LPlatform"): from ._lattice import LatticePlatform diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py new file mode 100755 index 000000000..9cdc8e72b --- /dev/null +++ b/amaranth/vendor/_gatemate.py @@ -0,0 +1,120 @@ +from abc import abstractmethod +from amaranth import * +from amaranth.build import * +from amaranth.lib.cdc import ResetSynchronizer + +__all__ = ["GateMatePlatform"] + +class GateMatePlatform(TemplatedPlatform): + """ + .. rubric:: GateMate FPGA toolchain + + Required tools: + * ``yosys`` + * ``p_r`` + + The environment is populated by setting the ``CC_TOOL`` environment variable to point to the toolchain directory. + """ + + device = property(abstractmethod(lambda: None)) + package = property(abstractmethod(lambda: None)) + + toolchain = "GateMate" + + required_tools = [ + "yosys", + "p_r", + ] + + file_templates = { + **TemplatedPlatform.build_script_templates, + "{{name}}.v": r""" + /* {{autogenerated}} */ + {{emit_verilog()}} + """, + "{{name}}.debug.v": r""" + /* {{autogenerated}} */ + {{emit_debug_verilog()}} + """, + "{{name}}.ccf": r""" + # {{autogenerated}} + {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%} + Net "{{port_name}}" Loc = "{{pin_name}}" + {%- set constraints = [ + "SCHMITT_TRIGGER", "PULLUP", "PULLDOWN", "KEEPER", "SLEW", "DRIVE", + "DELAY_OBF", "DELAY_IBF", "FF_IBF", "FF_OBF", "LVDS_BOOST", "LVDS_TERM" + ] -%} + {%- for constraint in constraints if constraint in attrs -%} + | {{constraint}}={{attrs[constraint]}} + {%- endfor -%}; + {% endfor %} + """, + "{{name}}.sdc": r""" + # {{autogenerated}} + {% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%} + {% if port_signal is not none -%} + create_clock -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_quote}}] + {% endif %} + {% endfor %} + """, + } + + command_templates = [ + r""" + mkdir -p log; + mkdir -p net; + {{invoke_tool("yosys")}} + -ql log/synth.log -p 'read -sv {{name}}.v; synth_gatemate -top {{name}} -nomx8 -vlog net/{{name}}_synth.v' + """, + r""" + + {{invoke_tool("p_r")}} + -v + -i net/{{name}}_synth.v + -o {{name}} + -ccf {{name}}.ccf + -cCP > log/impl.log + """, + ] + + # Common logic + + @property + def default_clk_constraint(self): + if self.default_clk == "sys_clk0": + return Clock(self.osc_freq / self.osc_div) + return super().default_clk_constraint + + def add_clock_constraint(self, clock, frequency): + super().add_clock_constraint(clock, frequency) + clock.attrs["keep"] = "TRUE" + + def create_missing_domain(self, name): + if name == "sync" and self.default_clk is not None: + m = Module() + if self.default_clk == "sys_clk0": + if not hasattr(self, "osc_div"): + raise ValueError("OSC divider (osc_div) must be an integer between 2 and 512") + if not isinstance(self.osc_div, int) or self.osc_div < 2 or self.osc_div > 512: + raise ValueError("OSC divider (osc_div) must be an integer between 2 and 512, not {!r}".format(self.osc_div)) + if not hasattr(self, "osc_freq"): + raise ValueError("OSC frequency (osc_freq) must be an integer between 2100000 and 80000000") + if not isinstance(self.osc_freq, int) or self.osc_freq < 2100000 or self.osc_freq > 80000000: + raise ValueError("OSC frequency (osc_freq) must be an integer between 2100000 and 80000000, not {!r}".format(self.osc_freq)) + clk_i = Signal() + sys_clk0 = Signal() + m.submodules += Instance("qlal4s3b_cell_macro", o_Sys_Clk0=sys_clk0) + m.submodules += Instance("gclkbuff", o_A=sys_clk0, o_Z=clk_i) + else: + clk_i = self.request(self.default_clk).i + + if self.default_rst is not None: + rst_i = self.request(self.default_rst).i + else: + rst_i = Const(0) + + m.domains += ClockDomain("sync") + m.d.comb += ClockSignal("sync").eq(clk_i) + m.submodules.reset_sync = ResetSynchronizer(rst_i, domain="sync") + return m + From 0580d1ab82319a37c4f787d360bd3e334ab7f0b2 Mon Sep 17 00:00:00 2001 From: TarikHamedovic <103156334+TarikHamedovic@users.noreply.github.com> Date: Tue, 23 Jul 2024 23:24:11 +0200 Subject: [PATCH 02/15] Update amaranth/vendor/_gatemate.py Two linebreaks between top-level items: Co-authored-by: Catherine --- amaranth/vendor/_gatemate.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 9cdc8e72b..ecd112487 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -3,8 +3,10 @@ from amaranth.build import * from amaranth.lib.cdc import ResetSynchronizer + __all__ = ["GateMatePlatform"] + class GateMatePlatform(TemplatedPlatform): """ .. rubric:: GateMate FPGA toolchain From 95bea8a59cf824f6a61378f470134a5c5e407f32 Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Tue, 23 Jul 2024 23:46:32 +0200 Subject: [PATCH 03/15] Update --- amaranth/vendor/_gatemate.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 9cdc8e72b..97c6d5335 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -3,17 +3,20 @@ from amaranth.build import * from amaranth.lib.cdc import ResetSynchronizer + + __all__ = ["GateMatePlatform"] + + class GateMatePlatform(TemplatedPlatform): """ - .. rubric:: GateMate FPGA toolchain Required tools: * ``yosys`` * ``p_r`` - The environment is populated by setting the ``CC_TOOL`` environment variable to point to the toolchain directory. + The environment is populated by setting the ``AMARANTH_ENV_GATEMATE`` environment variable to point to the toolchain directory. """ device = property(abstractmethod(lambda: None)) @@ -40,14 +43,10 @@ class GateMatePlatform(TemplatedPlatform): # {{autogenerated}} {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%} Net "{{port_name}}" Loc = "{{pin_name}}" - {%- set constraints = [ - "SCHMITT_TRIGGER", "PULLUP", "PULLDOWN", "KEEPER", "SLEW", "DRIVE", - "DELAY_OBF", "DELAY_IBF", "FF_IBF", "FF_OBF", "LVDS_BOOST", "LVDS_TERM" - ] -%} - {%- for constraint in constraints if constraint in attrs -%} - | {{constraint}}={{attrs[constraint]}} + {%- for constraint, value in attrs.items() -%} + | {{constraint}}={{value}} {%- endfor -%}; - {% endfor %} + {% endfor %} """, "{{name}}.sdc": r""" # {{autogenerated}} From 1eb30014ccd85bb169a467684a963eb136dd8bd2 Mon Sep 17 00:00:00 2001 From: TarikHamedovic <103156334+TarikHamedovic@users.noreply.github.com> Date: Wed, 24 Jul 2024 00:18:03 +0200 Subject: [PATCH 04/15] Update amaranth/vendor/_gatemate.py Added verbose("-v") instead of -v for p_r tool Co-authored-by: Catherine --- amaranth/vendor/_gatemate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 785a8e017..3d0d8c8d3 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -74,7 +74,7 @@ class GateMatePlatform(TemplatedPlatform): r""" {{invoke_tool("p_r")}} - -v + {{verbose("-v")}} -i net/{{name}}_synth.v -o {{name}} -ccf {{name}}.ccf From e3e65f893d3f36a321e6b52436bcb7263558dc34 Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Wed, 24 Jul 2024 00:18:36 +0200 Subject: [PATCH 05/15] Update --- amaranth/vendor/_gatemate.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 785a8e017..3a0f7027c 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -4,17 +4,11 @@ from amaranth.lib.cdc import ResetSynchronizer -<<<<<<< HEAD __all__ = ["GateMatePlatform"] -======= -__all__ = ["GateMatePlatform"] - - ->>>>>>> 0580d1ab82319a37c4f787d360bd3e334ab7f0b2 class GateMatePlatform(TemplatedPlatform): """ @@ -45,6 +39,23 @@ class GateMatePlatform(TemplatedPlatform): /* {{autogenerated}} */ {{emit_debug_verilog()}} """, + "{{name}}.ys": r""" + # {{autogenerated}} + {% for file in platform.iter_files(".v") -%} + read_verilog {{get_override("read_verilog_opts")|options}} {{file}} + {% endfor %} + {% for file in platform.iter_files(".sv") -%} + read_verilog -sv {{get_override("read_verilog_opts")|options}} {{file}} + {% endfor %} + {% for file in platform.iter_files(".il") -%} + read_ilang {{file}} + {% endfor %} + read_ilang {{name}}.il + {{get_override("script_after_read")|default("# (script_after_read placeholder)")}} + synth_gatemate {{get_override("synth_opts")|options}} -top {{name}} + {{get_override("script_after_synth")|default("# (script_after_synth placeholder)")}} + write_json {{name}}.json + """, "{{name}}.ccf": r""" # {{autogenerated}} {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%} @@ -66,8 +77,6 @@ class GateMatePlatform(TemplatedPlatform): command_templates = [ r""" - mkdir -p log; - mkdir -p net; {{invoke_tool("yosys")}} -ql log/synth.log -p 'read -sv {{name}}.v; synth_gatemate -top {{name}} -nomx8 -vlog net/{{name}}_synth.v' """, From ed3f252bbb3e5575de75bb9ee1731f2f7cf3e387 Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Wed, 24 Jul 2024 01:10:30 +0200 Subject: [PATCH 06/15] Update --- amaranth/vendor/__init__.py | 6 +++--- amaranth/vendor/_gatemate.py | 19 +++++++------------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/amaranth/vendor/__init__.py b/amaranth/vendor/__init__.py index 726020b76..b475ab862 100755 --- a/amaranth/vendor/__init__.py +++ b/amaranth/vendor/__init__.py @@ -28,12 +28,12 @@ def __getattr__(name): if name in ("AlteraPlatform", "IntelPlatform"): from ._altera import AlteraPlatform return AlteraPlatform - if name == "GowinPlatform": - from ._gowin import GowinPlatform - return GowinPlatform if name == "GateMatePlatform": from ._gatemate import GateMatePlatform return GateMatePlatform + if name == "GowinPlatform": + from ._gowin import GowinPlatform + return GowinPlatform if name in ("LatticePlatform", "LatticeECP5Platform", "LatticeMachXO2Platform", "LatticeMachXO3LPlatform"): from ._lattice import LatticePlatform diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index c8bb9d4e5..653a09c1d 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -42,19 +42,11 @@ class GateMatePlatform(TemplatedPlatform): "{{name}}.ys": r""" # {{autogenerated}} {% for file in platform.iter_files(".v") -%} - read_verilog {{get_override("read_verilog_opts")|options}} {{file}} + read -sv {{get_override("read_verilog_opts")|options}} {{file}} {% endfor %} - {% for file in platform.iter_files(".sv") -%} - read_verilog -sv {{get_override("read_verilog_opts")|options}} {{file}} - {% endfor %} - {% for file in platform.iter_files(".il") -%} - read_ilang {{file}} - {% endfor %} - read_ilang {{name}}.il {{get_override("script_after_read")|default("# (script_after_read placeholder)")}} - synth_gatemate {{get_override("synth_opts")|options}} -top {{name}} + synth_gatemate {{get_override("synth_opts")|options}} -top {{name}} -vlog {{name}}_synth.v {{get_override("script_after_synth")|default("# (script_after_synth placeholder)")}} - write_json {{name}}.json """, "{{name}}.ccf": r""" # {{autogenerated}} @@ -78,13 +70,16 @@ class GateMatePlatform(TemplatedPlatform): command_templates = [ r""" {{invoke_tool("yosys")}} - -ql log/synth.log -p 'read -sv {{name}}.v; synth_gatemate -top {{name}} -nomx8 -vlog net/{{name}}_synth.v' + {{quiet("-q")}} + {{get_override("yosys_opts")|options}} + -l {{name}}.rpt + {{name}}.ys """, r""" {{invoke_tool("p_r")}} {{verbose("-v")}} - -i net/{{name}}_synth.v + -i {{name}}_synth.v -o {{name}} -ccf {{name}}.ccf -cCP > log/impl.log From 857d8e763acc4771a8057fbbdf8dc90fa8176afc Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Wed, 24 Jul 2024 23:19:06 +0200 Subject: [PATCH 07/15] Update --- amaranth/vendor/_gatemate.py | 40 +++--------------------------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 653a09c1d..9417e429a 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -16,7 +16,8 @@ class GateMatePlatform(TemplatedPlatform): * ``yosys`` * ``p_r`` - The environment is populated by setting the ``AMARANTH_ENV_GATEMATE`` environment variable to point to the toolchain directory. + The environment is populated by running the script specified in the environment variable + ``AMARANTH_ENV_GATEMATE``, if present. """ device = property(abstractmethod(lambda: None)) @@ -88,42 +89,7 @@ class GateMatePlatform(TemplatedPlatform): # Common logic - @property - def default_clk_constraint(self): - if self.default_clk == "sys_clk0": - return Clock(self.osc_freq / self.osc_div) - return super().default_clk_constraint - def add_clock_constraint(self, clock, frequency): super().add_clock_constraint(clock, frequency) clock.attrs["keep"] = "TRUE" - - def create_missing_domain(self, name): - if name == "sync" and self.default_clk is not None: - m = Module() - if self.default_clk == "sys_clk0": - if not hasattr(self, "osc_div"): - raise ValueError("OSC divider (osc_div) must be an integer between 2 and 512") - if not isinstance(self.osc_div, int) or self.osc_div < 2 or self.osc_div > 512: - raise ValueError("OSC divider (osc_div) must be an integer between 2 and 512, not {!r}".format(self.osc_div)) - if not hasattr(self, "osc_freq"): - raise ValueError("OSC frequency (osc_freq) must be an integer between 2100000 and 80000000") - if not isinstance(self.osc_freq, int) or self.osc_freq < 2100000 or self.osc_freq > 80000000: - raise ValueError("OSC frequency (osc_freq) must be an integer between 2100000 and 80000000, not {!r}".format(self.osc_freq)) - clk_i = Signal() - sys_clk0 = Signal() - m.submodules += Instance("qlal4s3b_cell_macro", o_Sys_Clk0=sys_clk0) - m.submodules += Instance("gclkbuff", o_A=sys_clk0, o_Z=clk_i) - else: - clk_i = self.request(self.default_clk).i - - if self.default_rst is not None: - rst_i = self.request(self.default_rst).i - else: - rst_i = Const(0) - - m.domains += ClockDomain("sync") - m.d.comb += ClockSignal("sync").eq(clk_i) - m.submodules.reset_sync = ResetSynchronizer(rst_i, domain="sync") - return m - + From c3b8f9c339f265fa24af597bee6f18b50bacf557 Mon Sep 17 00:00:00 2001 From: Catherine Date: Wed, 24 Jul 2024 21:22:48 +0000 Subject: [PATCH 08/15] fix whitespace errors --- amaranth/vendor/_gatemate.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 9417e429a..1d4e2be6f 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -4,14 +4,11 @@ from amaranth.lib.cdc import ResetSynchronizer - __all__ = ["GateMatePlatform"] - class GateMatePlatform(TemplatedPlatform): """ - Required tools: * ``yosys`` * ``p_r`` @@ -77,7 +74,6 @@ class GateMatePlatform(TemplatedPlatform): {{name}}.ys """, r""" - {{invoke_tool("p_r")}} {{verbose("-v")}} -i {{name}}_synth.v @@ -92,4 +88,3 @@ class GateMatePlatform(TemplatedPlatform): def add_clock_constraint(self, clock, frequency): super().add_clock_constraint(clock, frequency) clock.attrs["keep"] = "TRUE" - From 231bbda30402a5ffc06e9fcaa74b594f7e515d57 Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Thu, 25 Jul 2024 00:12:43 +0200 Subject: [PATCH 09/15] Update yosys command_template --- amaranth/vendor/_gatemate.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 9417e429a..8ef64d2f2 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -32,9 +32,9 @@ class GateMatePlatform(TemplatedPlatform): file_templates = { **TemplatedPlatform.build_script_templates, - "{{name}}.v": r""" - /* {{autogenerated}} */ - {{emit_verilog()}} + "{{name}}.il": r""" + # {{autogenerated}} + {{emit_rtlil()}} """, "{{name}}.debug.v": r""" /* {{autogenerated}} */ @@ -43,8 +43,15 @@ class GateMatePlatform(TemplatedPlatform): "{{name}}.ys": r""" # {{autogenerated}} {% for file in platform.iter_files(".v") -%} - read -sv {{get_override("read_verilog_opts")|options}} {{file}} + read_verilog {{get_override("read_verilog_opts")|options}} {{file}} + {% endfor %} + {% for file in platform.iter_files(".sv") -%} + read_verilog -sv {{get_override("read_verilog_opts")|options}} {{file}} {% endfor %} + {% for file in platform.iter_files(".il") -%} + read_ilang {{file}} + {% endfor %} + read_ilang {{name}}.il {{get_override("script_after_read")|default("# (script_after_read placeholder)")}} synth_gatemate {{get_override("synth_opts")|options}} -top {{name}} -vlog {{name}}_synth.v {{get_override("script_after_synth")|default("# (script_after_synth placeholder)")}} @@ -83,7 +90,7 @@ class GateMatePlatform(TemplatedPlatform): -i {{name}}_synth.v -o {{name}} -ccf {{name}}.ccf - -cCP > log/impl.log + -cCP > {{name}}.tim """, ] @@ -92,4 +99,4 @@ class GateMatePlatform(TemplatedPlatform): def add_clock_constraint(self, clock, frequency): super().add_clock_constraint(clock, frequency) clock.attrs["keep"] = "TRUE" - + From 9c0e84b8b415ffecca47f597063749ac91778413 Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Thu, 25 Jul 2024 00:40:10 +0200 Subject: [PATCH 10/15] Added my Blinky example --- examples/Blinky.py | 132 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 examples/Blinky.py diff --git a/examples/Blinky.py b/examples/Blinky.py new file mode 100644 index 000000000..68fe8a710 --- /dev/null +++ b/examples/Blinky.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 + +from amaranth import * +from amaranth.sim import * +from amaranth.back import verilog + +import argparse +import subprocess +import importlib +import os +import shutil + +top_name = "Blinky" + +class Blinky(Elaboratable): + + def __init__(self, num_leds=1, clock_divider=21): + self.num_leds = num_leds + self.clock_divider = clock_divider + self.leds = Signal(num_leds) + + def elaborate(self, platform): + # Create a new Amaranth module + m = Module() + + # This is a local signal, which will not be accessible from outside. + count = Signal(self.clock_divider) + + # If the platform is not defined then it is simulation + if platform is not None: + + # ULX3S + #leds = [platform.request("led", i) for i in range(self.num_leds)] + #m.d.comb += [led.o.eq(self.leds[i]) for i, led in enumerate(leds)] + + # Olimex GateMate + led = platform.request("led", 0) + m.d.comb += led.o.eq(self.leds) + + # In the sync domain all logic is clocked at the positive edge of + # the implicit clk signal. + m.d.sync += count.eq(count + 1) + with m.If(count == (2**self.clock_divider - 1)): + m.d.sync += [ + self.leds.eq(~self.leds), + count.eq(0) + ] + + return m + + +def clean(): + files_to_remove = [f"{top_name}.vcd", f"{top_name}.gtkw", f"{top_name}.v"] + build_dir = "build" + + for file in files_to_remove: + try: + os.remove(file) + print(f"Removed {file}") + except FileNotFoundError: + print(f"{file} not found, skipping") + + if os.path.isdir(build_dir): + try: + shutil.rmtree(build_dir) + print(f"Removed {build_dir} directory") + except OSError as e: + print(f"Error removing {build_dir}: {e}") + +if __name__ == "__main__": + + parser = argparse.ArgumentParser() + parser.add_argument("-s", "--simulate", action="store_true", help="Simulate Blinky Example") + parser.add_argument("-b", "--build", action="store_true", help="Build The Blinky Example") + parser.add_argument("-v", "--verilog", action="store_true", help="Generate Verilog for Blinky Example") + parser.add_argument("-p", "--platform", type=str, required=False, help="Platform module (e.g., amaranth_boards.ulx3s.ULX3S_85F_Platform)") + parser.add_argument("-n", "--num-leds", type=int, default=1, help="Number of LEDs") + parser.add_argument("-cd", "--clock-divider", type=int, default=21, help="Clock divider (bit width of the counter)") + parser.add_argument("-cf", "--clock-frequency", type=float, default=1.0, help="Clock frequency in MHz") + parser.add_argument("-rt", "--runtime", type=int, default=30000, help="Testbench runtime in clock cycles") + parser.add_argument("-c", "--clean", action="store_true", help="Clean generated files and build directory") + parser.add_argument("-dp", "--do-program", action="store_true", help="Program the device after building") + parser.add_argument("-gw", "--gtkwave", action="store_true", help="Open GTKWave after simulation") + + args = parser.parse_args() + + if args.clean: + clean() + + else: + num_leds = args.num_leds if args.num_leds is not None else 1 + clock_divider = args.clock_divider if args.clock_divider is not None else 21 + clock_frequency = args.clock_frequency if args.clock_frequency is not None else 1.0 + runtime = args.runtime if args.runtime is not None else 30000 + do_program = args.do_program + + if args.simulate: + + def testbench(): + for _ in range(runtime): + yield Tick() + + # Instantiate the Blinky module + dut = Blinky(num_leds, clock_divider) + + # Create a simulator + sim = Simulator(dut) + sim.add_clock(1e-6 / clock_frequency) + sim.add_process(testbench) + with sim.write_vcd(f"{top_name}.vcd", f"{top_name}.gtkw", traces=[dut.leds]): + sim.run() + + # Open GTKWave with the generated VCD file if --gtkwave is set + if args.gtkwave: + subprocess.run(["gtkwave", f"{top_name}.vcd"]) + + elif args.build: + if args.platform is None: + raise ValueError("Platform must be specified for building") + platform_module_name, platform_class_name = args.platform.rsplit(".", 1) + platform_module = importlib.import_module(platform_module_name) + platform_class = getattr(platform_module, platform_class_name) + + plat = platform_class() + plat.build(Blinky(num_leds, clock_divider), do_program=do_program) + + elif args.verilog: + dut = Blinky(num_leds, clock_divider) + with open(f"{top_name}.v", "w") as f: + f.write(verilog.convert(dut, ports=[dut.leds])) + +# TODO: Maybe write an additional file where all of the amaranth_boards with their vendors are specified so that you can type ulx3s -85F instead of amaranth_boards.ulx3s.ULX3S_85F_Platform From 3760be1505e33a95b6d0033845b87d04ab611796 Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Thu, 25 Jul 2024 01:03:23 +0200 Subject: [PATCH 11/15] Deleted SDC file --- amaranth/vendor/_gatemate.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 88d2d8cb7..46e40fca5 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -62,14 +62,6 @@ class GateMatePlatform(TemplatedPlatform): {%- endfor -%}; {% endfor %} """, - "{{name}}.sdc": r""" - # {{autogenerated}} - {% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%} - {% if port_signal is not none -%} - create_clock -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_quote}}] - {% endif %} - {% endfor %} - """, } command_templates = [ From 0505ca58c688f8fa26c640c33bd3467e6a5a61f6 Mon Sep 17 00:00:00 2001 From: TarikHamedovic <103156334+TarikHamedovic@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:27:11 +0200 Subject: [PATCH 12/15] Update README.md Added GateMate vendor --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c09fce95..282ea5aa6 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,8 @@ Amaranth can be used to target any FPGA or ASIC process that accepts behavioral * AMD 7-series (toolchains: Vivado, ISE); * AMD UltraScale, UltraScale+ (toolchains: Vivado); * Altera (toolchains: Quartus); - * Quicklogic EOS S3 (toolchains: **Yosys+VPR**). + * Quicklogic EOS S3 (toolchains: **Yosys+VPR**); + * GateMate (toolchains: **Yosys**+GateMate p_r). FOSS toolchains are listed in **bold**. From 9a82d5370e04fc6ce034e8f177ff99e9eb3bc53a Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Thu, 25 Jul 2024 02:00:17 +0200 Subject: [PATCH 13/15] Removed unnecessary lines --- amaranth/vendor/_gatemate.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index 46e40fca5..e93089c1c 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -17,9 +17,6 @@ class GateMatePlatform(TemplatedPlatform): ``AMARANTH_ENV_GATEMATE``, if present. """ - device = property(abstractmethod(lambda: None)) - package = property(abstractmethod(lambda: None)) - toolchain = "GateMate" required_tools = [ From f63985035db6316d26586ecd438cffaac7783c36 Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Thu, 25 Jul 2024 02:00:30 +0200 Subject: [PATCH 14/15] Removed unnecessary lines --- amaranth/vendor/_gatemate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index e93089c1c..e4efed091 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -17,6 +17,7 @@ class GateMatePlatform(TemplatedPlatform): ``AMARANTH_ENV_GATEMATE``, if present. """ + toolchain = "GateMate" required_tools = [ From 006ca56c3a91e108e3b1dde54d3a43b648144ba8 Mon Sep 17 00:00:00 2001 From: TarikHamedovic Date: Thu, 25 Jul 2024 02:12:03 +0200 Subject: [PATCH 15/15] Changed yosys keep to appropriate form --- amaranth/vendor/_gatemate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amaranth/vendor/_gatemate.py b/amaranth/vendor/_gatemate.py index e4efed091..9e1aea57e 100755 --- a/amaranth/vendor/_gatemate.py +++ b/amaranth/vendor/_gatemate.py @@ -84,4 +84,4 @@ class GateMatePlatform(TemplatedPlatform): def add_clock_constraint(self, clock, frequency): super().add_clock_constraint(clock, frequency) - clock.attrs["keep"] = "TRUE" + clock.attrs["keep"] = True