From 0fac1f8d0f3a9d1ec798acd6a28e93089b8a1c02 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 12 Dec 2018 12:38:24 +0000 Subject: [PATCH] =?utf8?q?fhdl.dsl:=20comb/sync/sync.pix=E2=86=92d.comb/d.?= =?utf8?q?sync/d.pix.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- examples/alu.py | 20 +++++++-------- examples/alu_hier.py | 30 +++++++++++----------- examples/arst.py | 14 +++++----- examples/clkdiv.py | 14 +++++----- examples/ctrl.py | 14 +++++----- examples/pmux.py | 20 +++++++-------- nmigen/back/rtlil.py | 4 ++- nmigen/fhdl/dsl.py | 61 +++++++++++++++++++------------------------- nmigen/genlib/cdc.py | 11 +++++--- 9 files changed, 92 insertions(+), 96 deletions(-) diff --git a/examples/alu.py b/examples/alu.py index 1ffb176..456a75b 100644 --- a/examples/alu.py +++ b/examples/alu.py @@ -11,16 +11,16 @@ class ALU: self.co = Signal() def get_fragment(self, platform): - f = Module() - with f.If(self.sel == 0b00): - f.comb += self.o.eq(self.a | self.b) - with f.Elif(self.sel == 0b01): - f.comb += self.o.eq(self.a & self.b) - with f.Elif(self.sel == 0b10): - f.comb += self.o.eq(self.a ^ self.b) - with f.Else(): - f.comb += Cat(self.o, self.co).eq(self.a - self.b) - return f.lower(platform) + m = Module() + with m.If(self.sel == 0b00): + m.d.comb += self.o.eq(self.a | self.b) + with m.Elif(self.sel == 0b01): + m.d.comb += self.o.eq(self.a & self.b) + with m.Elif(self.sel == 0b10): + m.d.comb += self.o.eq(self.a ^ self.b) + with m.Else(): + m.d.comb += Cat(self.o, self.co).eq(self.a - self.b) + return m.lower(platform) alu = ALU(width=16) diff --git a/examples/alu_hier.py b/examples/alu_hier.py index 52d2c19..81640b2 100644 --- a/examples/alu_hier.py +++ b/examples/alu_hier.py @@ -9,9 +9,9 @@ class Adder: self.o = Signal(width) def get_fragment(self, platform): - f = Module() - f.comb += self.o.eq(self.a + self.b) - return f.lower(platform) + m = Module() + m.d.comb += self.o.eq(self.a + self.b) + return m.lower(platform) class Subtractor: @@ -21,9 +21,9 @@ class Subtractor: self.o = Signal(width) def get_fragment(self, platform): - f = Module() - f.comb += self.o.eq(self.a - self.b) - return f.lower(platform) + m = Module() + m.d.comb += self.o.eq(self.a - self.b) + return m.lower(platform) class ALU: @@ -37,20 +37,20 @@ class ALU: self.sub = Subtractor(width) def get_fragment(self, platform): - f = Module() - f.submodules.add = self.add - f.submodules.sub = self.sub - f.comb += [ + m = Module() + m.submodules.add = self.add + m.submodules.sub = self.sub + m.d.comb += [ self.add.a.eq(self.a), self.sub.a.eq(self.a), self.add.b.eq(self.b), self.sub.b.eq(self.b), ] - with f.If(self.op): - f.comb += self.o.eq(self.sub.o) - with f.Else(): - f.comb += self.o.eq(self.add.o) - return f.lower(platform) + with m.If(self.op): + m.d.comb += self.o.eq(self.sub.o) + with m.Else(): + m.d.comb += self.o.eq(self.add.o) + return m.lower(platform) alu = ALU(width=16) diff --git a/examples/arst.py b/examples/arst.py index c8fa8c7..d6fcd04 100644 --- a/examples/arst.py +++ b/examples/arst.py @@ -8,14 +8,14 @@ class ClockDivisor: self.o = Signal() def get_fragment(self, platform): - f = Module() - f.sync += self.v.eq(self.v + 1) - f.comb += self.o.eq(self.v[-1]) - return f.lower(platform) + m = Module() + m.d.sync += self.v.eq(self.v + 1) + m.d.comb += self.o.eq(self.v[-1]) + return m.lower(platform) -sys = ClockDomain(async_reset=True) +sync = ClockDomain(async_reset=True) ctr = ClockDivisor(factor=16) frag = ctr.get_fragment(platform=None) -# print(rtlil.convert(frag, ports=[sys.clk, sys.reset, ctr.o], clock_domains={"sys": sys})) -print(verilog.convert(frag, ports=[sys.clk, sys.reset, ctr.o], clock_domains={"sys": sys})) +# print(rtlil.convert(frag, ports=[sync.clk, sync.reset, ctr.o], clock_domains={"sync": sync})) +print(verilog.convert(frag, ports=[sync.clk, sync.reset, ctr.o], clock_domains={"sync": sync})) diff --git a/examples/clkdiv.py b/examples/clkdiv.py index f54505e..79eec93 100644 --- a/examples/clkdiv.py +++ b/examples/clkdiv.py @@ -8,14 +8,14 @@ class ClockDivisor: self.o = Signal() def get_fragment(self, platform): - f = Module() - f.sync += self.v.eq(self.v + 1) - f.comb += self.o.eq(self.v[-1]) - return f.lower(platform) + m = Module() + m.d.sync += self.v.eq(self.v + 1) + m.d.comb += self.o.eq(self.v[-1]) + return m.lower(platform) -sys = ClockDomain() +sync = ClockDomain() ctr = ClockDivisor(factor=16) frag = ctr.get_fragment(platform=None) -# print(rtlil.convert(frag, ports=[sys.clk, ctr.o], clock_domains={"sys": sys})) -print(verilog.convert(frag, ports=[sys.clk, ctr.o], clock_domains={"sys": sys})) +# print(rtlil.convert(frag, ports=[sync.clk, ctr.o], clock_domains={"sync": sync})) +print(verilog.convert(frag, ports=[sync.clk, ctr.o], clock_domains={"sync": sync})) diff --git a/examples/ctrl.py b/examples/ctrl.py index 9e6d76c..2d8fcf8 100644 --- a/examples/ctrl.py +++ b/examples/ctrl.py @@ -9,14 +9,14 @@ class ClockDivisor: self.ce = Signal() def get_fragment(self, platform): - f = Module() - f.sync += self.v.eq(self.v + 1) - f.comb += self.o.eq(self.v[-1]) - return CEInserter(self.ce)(f.lower()) + m = Module() + m.d.sync += self.v.eq(self.v + 1) + m.d.comb += self.o.eq(self.v[-1]) + return CEInserter(self.ce)(m.lower(platform)) -sys = ClockDomain() +sync = ClockDomain() ctr = ClockDivisor(factor=16) frag = ctr.get_fragment(platform=None) -# print(rtlil.convert(frag, ports=[sys.clk, ctr.o, ctr.ce], clock_domains={"sys": sys})) -print(verilog.convert(frag, ports=[sys.clk, ctr.o, ctr.ce], clock_domains={"sys": sys})) +# print(rtlil.convert(frag, ports=[sync.clk, ctr.o, ctr.ce], clock_domains={"sync": sync})) +print(verilog.convert(frag, ports=[sync.clk, ctr.o, ctr.ce], clock_domains={"sync": sync})) diff --git a/examples/pmux.py b/examples/pmux.py index be6c0d4..e69068b 100644 --- a/examples/pmux.py +++ b/examples/pmux.py @@ -11,16 +11,16 @@ class ParMux: self.o = Signal(width) def get_fragment(self, platform): - f = Module() - with f.Case(self.s, "--1"): - f.comb += self.o.eq(self.a) - with f.Case(self.s, "-1-"): - f.comb += self.o.eq(self.b) - with f.Case(self.s, "1--"): - f.comb += self.o.eq(self.c) - with f.Case(self.s): - f.comb += self.o.eq(0) - return f.lower(platform) + m = Module() + with m.Case(self.s, "--1"): + m.d.comb += self.o.eq(self.a) + with m.Case(self.s, "-1-"): + m.d.comb += self.o.eq(self.b) + with m.Case(self.s, "1--"): + m.d.comb += self.o.eq(self.c) + with m.Case(self.s): + m.d.comb += self.o.eq(0) + return m.lower(platform) pmux = ParMux(width=16) diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index 2bc20a4..eca4252 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -449,11 +449,13 @@ def convert_fragment(builder, fragment, name, clock_domains): triggers = [] if cd_name is None: triggers.append(("always",)) - else: + elif cd_name in clock_domains: cd = clock_domains[cd_name] triggers.append(("posedge", xformer(cd.clk))) if cd.async_reset: triggers.append(("posedge", xformer(cd.reset))) + else: + raise ValueError("Clock domain {} not found in design".format(cd_name)) for trigger in triggers: with process.sync(*trigger) as sync: diff --git a/nmigen/fhdl/dsl.py b/nmigen/fhdl/dsl.py index 2b14541..66759e8 100644 --- a/nmigen/fhdl/dsl.py +++ b/nmigen/fhdl/dsl.py @@ -14,36 +14,30 @@ class _ModuleBuilderProxy: object.__setattr__(self, "_depth", depth) -class _ModuleBuilderComb(_ModuleBuilderProxy): - def __iadd__(self, assigns): - self._builder._add_statement(assigns, cd=None, depth=self._depth) - return self - - -class _ModuleBuilderSyncCD(_ModuleBuilderProxy): - def __init__(self, builder, depth, cd): +class _ModuleBuilderDomain(_ModuleBuilderProxy): + def __init__(self, builder, depth, cd_name): super().__init__(builder, depth) - self._cd = cd + self._cd_name = cd_name def __iadd__(self, assigns): - self._builder._add_statement(assigns, cd=self._cd, depth=self._depth) + self._builder._add_statement(assigns, cd_name=self._cd_name, depth=self._depth) return self -class _ModuleBuilderSync(_ModuleBuilderProxy): - def __iadd__(self, assigns): - self._builder._add_statement(assigns, cd="sys", depth=self._depth) - return self - +class _ModuleBuilderDomains(_ModuleBuilderProxy): def __getattr__(self, name): - return _ModuleBuilderSyncCD(self._builder, self._depth, name) + if name == "comb": + cd_name = None + else: + cd_name = name + return _ModuleBuilderDomain(self._builder, self._depth, cd_name) def __getitem__(self, name): return self.__getattr__(name) def __setattr__(self, name, value): - if not isinstance(value, _ModuleBuilderSyncCD): - raise AttributeError("Cannot assign sync.{} attribute - use += instead" + if not isinstance(value, _ModuleBuilderDomain): + raise AttributeError("Cannot assign d.{} attribute - use += instead" .format(name)) def __setitem__(self, name, value): @@ -53,15 +47,12 @@ class _ModuleBuilderSync(_ModuleBuilderProxy): class _ModuleBuilderRoot: def __init__(self, builder, depth): self._builder = builder - self.comb = _ModuleBuilderComb(builder, depth) - self.sync = _ModuleBuilderSync(builder, depth) + self.domain = self.d = _ModuleBuilderDomains(builder, depth) - def __setattr__(self, name, value): - if name == "comb" and not isinstance(value, _ModuleBuilderComb): - raise AttributeError("Cannot assign comb attribute - use += instead") - if name == "sync" and not isinstance(value, _ModuleBuilderSync): - raise AttributeError("Cannot assign sync attribute - use += instead") - super().__setattr__(name, value) + def __getattr__(self, name): + if name in ("comb", "sync"): + raise AttributeError("'{}' object has no attribute '{}'; did you mean 'd.{}'?" + .format(type(self).__name__, name, name)) class _ModuleBuilderIf(_ModuleBuilderRoot): @@ -201,12 +192,12 @@ class Module(_ModuleBuilderRoot): self._stmt_switch_test = None self._stmt_switch_cases = OrderedDict() - def _add_statement(self, assigns, cd, depth): - def cd_name(cd): - if cd is None: + def _add_statement(self, assigns, cd_name, depth): + def cd_human_name(cd_name): + if cd_name is None: return "comb" else: - return "sync.{}".format(cd) + return cd_name if depth < self._stmt_depth: self._flush() @@ -218,12 +209,12 @@ class Module(_ModuleBuilderRoot): for signal in assign.lhs._lhs_signals(): if signal not in self._driving: - self._driving[signal] = cd - elif self._driving[signal] != cd: + self._driving[signal] = cd_name + elif self._driving[signal] != cd_name: cd_curr = self._driving[signal] - raise ValueError("Driver-driver conflict: trying to drive {!r} from {}, but " - "it is already driven from {}" - .format(signal, self.cd_name(cd), self.cd_name(cd_curr))) + raise ValueError("Driver-driver conflict: trying to drive {!r} from d.{}, but " + "it is already driven from d.{}" + .format(signal, cd_human_name(cd), cd_human_name(cd_curr))) self._statements.append(assign) diff --git a/nmigen/genlib/cdc.py b/nmigen/genlib/cdc.py index a6c1fc2..1b5fffc 100644 --- a/nmigen/genlib/cdc.py +++ b/nmigen/genlib/cdc.py @@ -15,8 +15,11 @@ class MultiReg: for i in range(n)] def get_fragment(self, platform): - f = Module() + if hasattr(platform, "get_multi_reg"): + return platform.get_multi_reg(self) + + m = Module() for i, o in zip((self.i, *self._regs), self._regs): - f.sync[self.odomain] += o.eq(i) - f.comb += self.o.eq(self._regs[-1]) - return f.lower(platform) + m.d[self.odomain] += o.eq(i) + m.d.comb += self.o.eq(self._regs[-1]) + return m.lower(platform) -- 2.30.2