From ec7cfdd719dcf80494a44fe43e35607c08110e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Nguyen?= Date: Wed, 13 Jul 2022 20:23:34 +0200 Subject: [PATCH] cores/microwatt: move microwatt.py to its own python module. Also: * update dependencies. * add amaranth-soc as a dependency, in order to reuse its bus interfaces (e.g. Wishbone). * add a `prog` argument to PowerFVSession that overrides the name of its CLI. --- cores/microwatt/README.md | 2 +- cores/microwatt/checks.pfv | 2 +- cores/microwatt/microwatt/__init__.py | 0 cores/microwatt/microwatt/__main__.py | 13 ++ .../{microwatt.py => microwatt/core.py} | 172 +++++++++--------- poetry.lock | 51 ++++-- power_fv/session.py | 11 +- pyproject.toml | 1 + 8 files changed, 145 insertions(+), 107 deletions(-) create mode 100644 cores/microwatt/microwatt/__init__.py create mode 100644 cores/microwatt/microwatt/__main__.py rename cores/microwatt/{microwatt.py => microwatt/core.py} (69%) diff --git a/cores/microwatt/README.md b/cores/microwatt/README.md index 4317d7e..47f79ea 100644 --- a/cores/microwatt/README.md +++ b/cores/microwatt/README.md @@ -7,7 +7,7 @@ Get Microwatt: ``` -git clone git@git.openpower.foundation:jfng/microwatt -b powerfv microwatt-src +git clone git@git.openpower.foundation:jfng/microwatt -b powerfv src ``` ## Usage diff --git a/cores/microwatt/checks.pfv b/cores/microwatt/checks.pfv index 087cba7..1e8b5ce 100644 --- a/cores/microwatt/checks.pfv +++ b/cores/microwatt/checks.pfv @@ -3,5 +3,5 @@ check cia --depth=15 check gpr --depth=15 check insn --depth=15 -build --build-dir=./build --src-dir=./microwatt-src +build --build-dir=./build --src-dir=./src exit diff --git a/cores/microwatt/microwatt/__init__.py b/cores/microwatt/microwatt/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cores/microwatt/microwatt/__main__.py b/cores/microwatt/microwatt/__main__.py new file mode 100644 index 0000000..b492503 --- /dev/null +++ b/cores/microwatt/microwatt/__main__.py @@ -0,0 +1,13 @@ +from pathlib import PurePath +from power_fv.session import PowerFVSession + +from .core import MicrowattCore + + +class MicrowattSession(PowerFVSession, core_cls=MicrowattCore): + pass + + +if __name__ == "__main__": + PROG = "python -m {}".format(PurePath(__file__).parent.name) + MicrowattSession(prog=PROG).main() diff --git a/cores/microwatt/microwatt.py b/cores/microwatt/microwatt/core.py similarity index 69% rename from cores/microwatt/microwatt.py rename to cores/microwatt/microwatt/core.py index 6b05e72..cbef745 100644 --- a/cores/microwatt/microwatt.py +++ b/cores/microwatt/microwatt/core.py @@ -4,13 +4,13 @@ import textwrap from amaranth import * from amaranth.asserts import * +from amaranth_soc import wishbone from power_fv import pfv from power_fv.core import PowerFVCore -from power_fv.session import PowerFVSession -__all__ = ["MicrowattWrapper", "MicrowattCore", "MicrowattSession"] +__all__ = ["MicrowattWrapper", "MicrowattCore"] class MicrowattWrapper(Elaboratable): @@ -134,50 +134,59 @@ class MicrowattWrapper(Elaboratable): """) def __init__(self, **kwargs): - self.pfv = pfv.Interface() - self._kwargs = kwargs + self.pfv = pfv.Interface() + self.wb_insn = wishbone.Interface(addr_width=29, data_width=64, granularity=8, + features=("stall",)) + self.wb_data = wishbone.Interface(addr_width=29, data_width=64, granularity=8, + features=("stall",)) - def _render_toplevel(self): - return self.MICROWATT_TOPLEVEL.format(**self._kwargs) + def keep_wb_fanout(wb_bus): + for field_name in ("adr", "dat_w", "sel", "cyc", "stb", "we"): + wb_bus[field_name].attrs["keep"] = True + + keep_wb_fanout(self.wb_insn) + keep_wb_fanout(self.wb_data) + + self._toplevel_src = self.MICROWATT_TOPLEVEL.format(**kwargs) def elaborate(self, platform): m = Module() - wb_insn_dat_r = AnySeq(64) - wb_insn_ack = AnySeq( 1) - wb_insn_stall = AnySeq( 1) - wb_insn_adr = Signal(29, attrs={"keep": True}) - wb_insn_dat_w = Signal(64, attrs={"keep": True}) - wb_insn_sel = Signal( 8, attrs={"keep": True}) - wb_insn_cyc = Signal( attrs={"keep": True}) - wb_insn_stb = Signal( attrs={"keep": True}) - wb_insn_we = Signal( attrs={"keep": True}) - - wb_data_dat_r = AnySeq(64) - wb_data_ack = AnySeq( 1) - wb_data_stall = AnySeq( 1) - wb_data_adr = Signal(29, attrs={"keep": True}) - wb_data_dat_w = Signal(64, attrs={"keep": True}) - wb_data_sel = Signal( 8, attrs={"keep": True}) - wb_data_cyc = Signal( 1, attrs={"keep": True}) - wb_data_stb = Signal( 1, attrs={"keep": True}) - wb_data_we = Signal( 1, attrs={"keep": True}) - - wb_snoop_adr = AnySeq(29) - wb_snoop_dat_w = AnySeq(64) - wb_snoop_sel = AnySeq( 8) - wb_snoop_cyc = AnySeq( 1) - wb_snoop_stb = AnySeq( 1) - wb_snoop_we = AnySeq( 1) - - dmi_addr = AnySeq( 4) - dmi_din = AnySeq(64) - dmi_req = AnySeq( 1) - dmi_wr = AnySeq( 1) - dmi_dout = Signal(64, attrs={"keep": True}) - dmi_ack = Signal( attrs={"keep": True}) - - terminated = Signal( attrs={"keep": True}) + wb_snoop = wishbone.Interface(addr_width=29, data_width=64, granularity=8) + dmi = Record([ + ("addr", unsigned( 4)), + ("din", unsigned(64)), + ("dout", unsigned(64)), + ("req", unsigned( 1)), + ("wr", unsigned( 1)), + ("ack", unsigned( 1)), + ]) + terminated = Signal(attrs={"keep": True}) + + dmi.dout.attrs["keep"] = True + dmi.ack .attrs["keep"] = True + + m.d.comb += [ + self.wb_insn.dat_r.eq(AnySeq(64)), + self.wb_insn.ack .eq(AnySeq( 1)), + self.wb_insn.stall.eq(AnySeq( 1)), + + self.wb_data.dat_r.eq(AnySeq(64)), + self.wb_data.ack .eq(AnySeq( 1)), + self.wb_data.stall.eq(AnySeq( 1)), + + wb_snoop.adr .eq(AnySeq(29)), + wb_snoop.dat_w.eq(AnySeq(64)), + wb_snoop.sel .eq(AnySeq( 8)), + wb_snoop.cyc .eq(AnySeq( 1)), + wb_snoop.stb .eq(AnySeq( 1)), + wb_snoop.we .eq(AnySeq( 1)), + + dmi.addr.eq(AnySeq( 4)), + dmi.din .eq(AnySeq(64)), + dmi.req .eq(AnySeq( 1)), + dmi.wr .eq(AnySeq( 1)), + ] m.submodules.dut = Instance("toplevel", ("i", "clk", ClockSignal()), @@ -185,39 +194,39 @@ class MicrowattWrapper(Elaboratable): ("i", "alt_reset", Const(0)), ("i", "ext_irq", Const(0)), - ("i", "wishbone_insn_in.dat" , wb_insn_dat_r), - ("i", "wishbone_insn_in.ack" , wb_insn_ack ), - ("i", "wishbone_insn_in.stall", wb_insn_stall), - ("o", "wishbone_insn_out.adr" , wb_insn_adr ), - ("o", "wishbone_insn_out.dat" , wb_insn_dat_w), - ("o", "wishbone_insn_out.sel" , wb_insn_sel ), - ("o", "wishbone_insn_out.cyc" , wb_insn_cyc ), - ("o", "wishbone_insn_out.stb" , wb_insn_stb ), - ("o", "wishbone_insn_out.we" , wb_insn_we ), - - ("i", "wishbone_data_in.dat" , wb_data_dat_r), - ("i", "wishbone_data_in.ack" , wb_data_ack ), - ("i", "wishbone_data_in.stall", wb_data_stall), - ("o", "wishbone_data_out.adr" , wb_data_adr ), - ("o", "wishbone_data_out.dat" , wb_data_dat_w), - ("o", "wishbone_data_out.sel" , wb_data_sel ), - ("o", "wishbone_data_out.cyc" , wb_data_cyc ), - ("o", "wishbone_data_out.stb" , wb_data_stb ), - ("o", "wishbone_data_out.we" , wb_data_we ), - - ("i", "wb_snoop_in.adr", wb_snoop_adr ), - ("i", "wb_snoop_in.dat", wb_snoop_dat_w), - ("i", "wb_snoop_in.sel", wb_snoop_sel ), - ("i", "wb_snoop_in.cyc", wb_snoop_cyc ), - ("i", "wb_snoop_in.stb", wb_snoop_stb ), - ("i", "wb_snoop_in.we" , wb_snoop_we ), - - ("i", "dmi_addr", dmi_addr), - ("i", "dmi_din" , dmi_din ), - ("o", "dmi_dout", dmi_dout), - ("i", "dmi_req" , dmi_req ), - ("i", "dmi_wr" , dmi_wr ), - ("o", "dmi_ack" , dmi_ack ), + ("i", "wishbone_insn_in.dat" , self.wb_insn.dat_r), + ("i", "wishbone_insn_in.ack" , self.wb_insn.ack ), + ("i", "wishbone_insn_in.stall", self.wb_insn.stall), + ("o", "wishbone_insn_out.adr" , self.wb_insn.adr ), + ("o", "wishbone_insn_out.dat" , self.wb_insn.dat_w), + ("o", "wishbone_insn_out.sel" , self.wb_insn.sel ), + ("o", "wishbone_insn_out.cyc" , self.wb_insn.cyc ), + ("o", "wishbone_insn_out.stb" , self.wb_insn.stb ), + ("o", "wishbone_insn_out.we" , self.wb_insn.we ), + + ("i", "wishbone_data_in.dat" , self.wb_data.dat_r), + ("i", "wishbone_data_in.ack" , self.wb_data.ack ), + ("i", "wishbone_data_in.stall", self.wb_data.stall), + ("o", "wishbone_data_out.adr" , self.wb_data.adr ), + ("o", "wishbone_data_out.dat" , self.wb_data.dat_w), + ("o", "wishbone_data_out.sel" , self.wb_data.sel ), + ("o", "wishbone_data_out.cyc" , self.wb_data.cyc ), + ("o", "wishbone_data_out.stb" , self.wb_data.stb ), + ("o", "wishbone_data_out.we" , self.wb_data.we ), + + ("i", "wb_snoop_in.adr", wb_snoop.adr ), + ("i", "wb_snoop_in.dat", wb_snoop.dat_w), + ("i", "wb_snoop_in.sel", wb_snoop.sel ), + ("i", "wb_snoop_in.cyc", wb_snoop.cyc ), + ("i", "wb_snoop_in.stb", wb_snoop.stb ), + ("i", "wb_snoop_in.we" , wb_snoop.we ), + + ("i", "dmi_addr", dmi.addr), + ("i", "dmi_din" , dmi.din ), + ("o", "dmi_dout", dmi.dout), + ("i", "dmi_req" , dmi.req ), + ("i", "dmi_wr" , dmi.wr ), + ("o", "dmi_ack" , dmi.ack ), ("o", "terminated_out", terminated), @@ -231,6 +240,7 @@ class MicrowattWrapper(Elaboratable): ("o", "pfv_out.rb" , self.pfv.rb ), ("o", "pfv_out.rs" , self.pfv.rs ), ("o", "pfv_out.rt" , self.pfv.rt ), + ("o", "pfv_out.mem" , self.pfv.mem ), ("o", "pfv_out.cr" , self.pfv.cr ), ("o", "pfv_out.msr" , self.pfv.msr ), ("o", "pfv_out.lr" , self.pfv.lr ), @@ -242,7 +252,7 @@ class MicrowattWrapper(Elaboratable): ) m.d.comb += [ - Assume(~dmi_req), + Assume(~dmi.req), Assume(~terminated), ] @@ -301,7 +311,7 @@ class MicrowattCore(PowerFVCore): super().add_build_arguments(parser) group = parser.add_argument_group(title="microwatt options") group.add_argument( - "--src-dir", type=pathlib.Path, default=pathlib.Path("./microwatt-src"), + "--src-dir", type=pathlib.Path, default=pathlib.Path("./src"), help="microwatt directory (default: %(default)s)") group.add_argument( "--ghdl-opts", type=str, default="--std=08", @@ -316,13 +326,5 @@ class MicrowattCore(PowerFVCore): platform.add_file(filename, contents) top_filename = "top-powerfv.vhdl" - top_contents = wrapper._render_toplevel() + top_contents = wrapper._toplevel_src platform.add_file(top_filename, top_contents) - - -class MicrowattSession(PowerFVSession, core_cls=MicrowattCore): - pass - - -if __name__ == "__main__": - MicrowattSession().main() diff --git a/poetry.lock b/poetry.lock index b267401..ccce1fe 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,16 +1,16 @@ [[package]] name = "amaranth" -version = "0.4.dev11+g85d56a7" +version = "0.4.dev21+gdb49294" description = "Amaranth hardware definition language" category = "main" optional = false -python-versions = "~=3.6" +python-versions = "~=3.7" develop = false [package.dependencies] importlib-resources = {version = "*", markers = "python_version < \"3.9\""} Jinja2 = ">=3.0,<4.0" -pyvcd = ">=0.2.2,<0.3.0" +pyvcd = ">=0.2.2,<0.4" [package.extras] builtin-yosys = ["amaranth-yosys (>=0.10)"] @@ -20,11 +20,29 @@ remote-build = ["paramiko (>=2.7,<3.0)"] type = "git" url = "https://github.com/amaranth-lang/amaranth.git" reference = "main" -resolved_reference = "85d56a74a595bac5b4423ace5462bc7452cfacbb" +resolved_reference = "db49294cf722e9463666bd06f81a86f930b8707c" + +[[package]] +name = "amaranth-soc" +version = "0.1.dev49+g217d4ea" +description = "System on Chip toolkit for Amaranth HDL" +category = "main" +optional = false +python-versions = "*" +develop = false + +[package.dependencies] +amaranth = ">=0.2,<0.5" + +[package.source] +type = "git" +url = "https://github.com/amaranth-lang/amaranth-soc.git" +reference = "main" +resolved_reference = "217d4ea76ad3b3bbf146980d168bc7b3b9d95a18" [[package]] name = "importlib-resources" -version = "5.6.0" +version = "5.8.0" description = "Read resources from Python packages" category = "main" optional = false @@ -61,7 +79,7 @@ python-versions = ">=3.7" [[package]] name = "pyvcd" -version = "0.2.4" +version = "0.3.0" description = "Python VCD file support" category = "main" optional = false @@ -69,26 +87,27 @@ python-versions = ">=3.6" [[package]] name = "zipp" -version = "3.7.0" +version = "3.8.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false python-versions = ">=3.7" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "8fbc350384d13e8a190df593335a502436e6b99dbf5aafefa5167db8c09206d6" +content-hash = "1c881976fce28a8b6924ba8df05bfa648b0c6098b5489df50523e968a6bfce73" [metadata.files] amaranth = [] +amaranth-soc = [] importlib-resources = [ - {file = "importlib_resources-5.6.0-py3-none-any.whl", hash = "sha256:a9dd72f6cc106aeb50f6e66b86b69b454766dd6e39b69ac68450253058706bcc"}, - {file = "importlib_resources-5.6.0.tar.gz", hash = "sha256:1b93238cbf23b4cde34240dd8321d99e9bf2eb4bc91c0c99b2886283e7baad85"}, + {file = "importlib_resources-5.8.0-py3-none-any.whl", hash = "sha256:7952325ffd516c05a8ad0858c74dff2c3343f136fe66a6002b2623dd1d43f223"}, + {file = "importlib_resources-5.8.0.tar.gz", hash = "sha256:568c9f16cb204f9decc8d6d24a572eeea27dacbb4cee9e6b03a8025736769751"}, ] jinja2 = [ {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, @@ -137,10 +156,10 @@ markupsafe = [ {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, ] pyvcd = [ - {file = "pyvcd-0.2.4-py2.py3-none-any.whl", hash = "sha256:c40b0e586a74cddaf82e6989f0168ae7f9b4f182a9a106a0da9df0d11a9c6b3b"}, - {file = "pyvcd-0.2.4.tar.gz", hash = "sha256:071e51a8362908ad5a2a12f078185639b98b20b653a56f01679de169d0fa425d"}, + {file = "pyvcd-0.3.0-py2.py3-none-any.whl", hash = "sha256:971dfe5a3e68663115c6edf3f0b611ff9e8427513db16281eb4516ebcd65a336"}, + {file = "pyvcd-0.3.0.tar.gz", hash = "sha256:ec4d9198bd20f9e07d78f6558ff8bcd45b172ee332e7e8a4588727eeb6a362bc"}, ] zipp = [ - {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, - {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"}, + {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, + {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, ] diff --git a/power_fv/session.py b/power_fv/session.py index d88d2cf..a94450f 100644 --- a/power_fv/session.py +++ b/power_fv/session.py @@ -37,8 +37,8 @@ class PowerFVSession: .format(core_cls)) cls.core_cls = core_cls - def __init__(self): - self.parser = _ArgumentParser(add_help=False) + def __init__(self, prog=None): + self.parser = _ArgumentParser(prog=prog, add_help=False) self.subparsers = self.parser.add_subparsers(help="commands") self.namespace = dict() @@ -50,7 +50,7 @@ class PowerFVSession: self.add_exit_subparser() def main(self): - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(prog=self.parser.prog) group = parser.add_mutually_exclusive_group() group.add_argument( "-i", dest="interact", action="store_true", @@ -60,7 +60,10 @@ class PowerFVSession: help="run commands from CMDFILE") args = parser.parse_args() - self._loop(args) + try: + self._loop(args) + except EOFError: + pass def _loop(self, args): if args.cmdfile is None: diff --git a/pyproject.toml b/pyproject.toml index f9198e1..4a9b1d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ license = "BSD" python = "^3.8" jinja2 = "~3.0" amaranth = {git = "https://github.com/amaranth-lang/amaranth.git", branch="main"} +amaranth_soc = {git = "https://github.com/amaranth-lang/amaranth-soc.git", branch="main"} [build-system] requires = ["poetry-core"]