mmu.py fix formatting, use Cat() where '&' in mmu.vhdl
authorCole Poirier <colepoirier@gmail.com>
Tue, 11 Aug 2020 21:48:53 +0000 (14:48 -0700)
committerCole Poirier <colepoirier@gmail.com>
Tue, 11 Aug 2020 21:48:53 +0000 (14:48 -0700)
src/soc/experiment/mmu.py

index aeda3a585ed58f09b76230bfc7f8ee8ff92c7b4b..96a60d45292fb741596a1a98d5207173e0c5779f 100644 (file)
@@ -9,12 +9,14 @@ from nmigen import (Module, Signal, Elaboratable, Mux, Cat, Repl, signed,
 from nmigen.cli import main
 from nmigen.iocontrol import RecordObject
 
-# library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
+# library ieee; use ieee.std_logic_1164.all;
+#               use ieee.numeric_std.all;
 
 # library work; use work.common.all;
 
 # -- Radix MMU
-# -- Supports 4-level trees as in arch 3.0B, but not the two-step translation
+# -- Supports 4-level trees as in arch 3.0B, but not the
+# -- two-step translation
 # -- for guests under a hypervisor (i.e. there is no gRA -> hRA translation).
 
 # type state_t is
@@ -109,8 +111,9 @@ class RegStage(RecordObject):
 
 
 # Radix MMU
-# Supports 4-level trees as in arch 3.0B, but not the two-step translation
-# for guests under a hypervisor (i.e. there is no gRA -> hRA translation).
+# Supports 4-level trees as in arch 3.0B, but not the
+# two-step translation for guests under a hypervisor
+# (i.e. there is no gRA -> hRA translation).
 class MMU(Elaboratable):
 # entity mmu is
 #     port (
@@ -133,83 +136,88 @@ class MMU(Elaboratable):
         self.d_in  = DcacheToMmuType()
         self.i_out = MmuToIcacheType()
 
-    def elaborate(self, platform):
-#   -- Multiplex internal SPR values back to loadstore1, selected
-#   -- by l_in.sprn.
+#       signal addrsh  : std_ulogic_vector(15 downto 0);
+#       signal mask    : std_ulogic_vector(15 downto 0);
+#       signal finalmask : std_ulogic_vector(43 downto 0);
+        self.addrsh = Signal(16)
+        self.mask = Signal(16)
+        self.finalmask = Signal(44)
 
-        # Multiplex internal SPR values back to loadstore1, selected by
-        # l_in.sprn.
+#       signal r, rin : reg_stage_t;
+        self.r = RegStage()
+        self.rin = RegStage()
+
+# begin
+def elaborate(self, platform):
+#       -- Multiplex internal SPR values back to loadstore1,
+#       -- selected by l_in.sprn.
+        # Multiplex internal SPR values back to loadstore1,
+        # selected by l_in.sprn.
         m = Module()
 
         comb = m.d.comb
         sync = m.d.sync
 
         rst = ResetSignal()
-        l_in = self.l_in
+
+        l_in  = self.l_in
         l_out = self.l_out
         d_out = self.d_out
-        d_in = self.d_in
+        d_in  = self.d_in
         i_out = self.i_out
 
-        # non-existant variable, to be removed when I understand how to do VHDL
-        # rising_edge(clk) in nmigen
-        rising_edge = False
-
-#       signal r, rin : reg_stage_t;
-        r = RegStage()
-        rin = RegStage()
-
-#       signal addrsh  : std_ulogic_vector(15 downto 0);
-#       signal mask    : std_ulogic_vector(15 downto 0);
-#       signal finalmask : std_ulogic_vector(43 downto 0);
-        addrsh = Signal(16)
-        mask = Signal(16)
-        finalmask = Signal(44)
+        addrsh    = self.addrsh
+        mask      = self.mask
+        finalmask = self.finalmask
 
-#   begin
+        r = self.r
+        rin = self.rin
 
 #       l_out.sprval <= r.prtbl when l_in.sprn(9) = '1'
-        with m.If(l_in.sprn[9] == 1):
+        with m.If(l_in.sprn[9]):
             comb += l_out.sprval.eq(r.prtbl)
 
 #       else x"00000000" & r.pid;
         with m.Else():
-            comb += l_out.sprval.eq(0x00000000 & r)
+            comb += l_out.sprval.eq(Cat(r.pid,
+                                    Const(0x00000000, 8))
 
 #       if rin.valid = '1' then
-#           report "MMU got tlb miss for " & to_hstring(rin.addr);
+#           report "MMU got tlb miss for "
+#                   & to_hstring(rin.addr);
 #       end if;
-        with m.If(rin.valid == 1):
+        with m.If(rin.valid):
             print(f"MMU got tlb miss for {rin.addr}")
 
 #       if l_out.done = '1' then
 #           report "MMU completing op without error";
 #       end if;
-        with m.If(l_out.done == 1):
+        with m.If(l_out.done):
             print("MMU completing op without error")
 
 #       if l_out.err = '1' then
 #           report "MMU completing op with err invalid=" &
-#                   std_ulogic'image(l_out.invalid) & " badtree=" &
-#                   std_ulogic'image(l_out.badtree);
+#                   std_ulogic'image(l_out.invalid) &
+#                   " badtree=" & std_ulogic'image(
+#                   l_out.badtree);
 #       end if;
-        with m.If(l_out.err == 1):
-            print(f"MMU completing op with err invalid={l_out.invalid}
-                  badtree={l_out.badtree}")
+        with m.If(l_out.err):
+            print(f"MMU completing op with err invalid=
+                  {l_out.invalid} badtree={l_out.badtree}")
 
 #       if rin.state = RADIX_LOOKUP then
-#           report "radix lookup shift=" & integer'image(to_integer(
-#                   rin.shift)) & " msize=" & integer'image(to_integer(
-#                   rin.mask_size));
+#           report "radix lookup shift=" & integer'image(
+#                   to_integer(rin.shift)) & " msize=" &
+#                   integer'image(to_integer(rin.mask_size));
 #       end if;
         with m.If(rin.state == State.RADIX_LOOKUP):
             print(f"radix lookup shift={rin.shift}
                   msize={rin.mask_size}")
 
 #       if r.state = RADIX_LOOKUP then
-#           report "send load addr=" & to_hstring(d_out.addr) &
-#                  " addrsh=" & to_hstring(addrsh) & " mask=" &
-#                  to_hstring(mask);
+#           report "send load addr=" & to_hstring(d_out.addr)
+#                   & " addrsh=" & to_hstring(addrsh) &
+#                   " mask=" & to_hstring(mask);
 #       end if;
         with m.If(r.state == State.RADIX_LOOKUP):
             print(f"send load addr={d_out.addr}
@@ -219,23 +227,21 @@ class MMU(Elaboratable):
         sync += r.eq(rin)
 # end process;
 
-#     -- Shift address bits 61--12 right by 0--47 bits and
-#     -- supply the least significant 16 bits of the result.
-#     addrshifter: process(all)
-
+# -- Shift address bits 61--12 right by 0--47 bits and
+# -- supply the least significant 16 bits of the result.
+# -- addrshifter: process(all)
 # Shift address bits 61--12 right by 0--47 bits and
 # supply the least significant 16 bits of the result.
-class AddrShifter(Elaboratable):
-
+class AddrShifter(Elaboratable, MMU):
     def __init__(self):
 #       variable sh1 : std_ulogic_vector(30 downto 0);
 #       variable sh2 : std_ulogic_vector(18 downto 0);
 #       variable result : std_ulogic_vector(15 downto 0);
+        super().__init__()
         self.sh1 = Signal(31)
         self.sh2 = Signal(19)
         self.result = Signal(16)
 
-
 #   begin
     def elaborate(self, platform):
 
@@ -246,39 +252,43 @@ class AddrShifter(Elaboratable):
 
         rst = ResetSignal()
 
-        sh1 = self.sh1
-        sh2 = self.sh2
+        r      = self.r
+        addrsh = self.addrsh
+
+        sh1    = self.sh1
+        sh2    = self.sh2
         result = self.result
 
 #       case r.shift(5 downto 4) is
         with m.Switch(r.shift[4:6]):
 #           when "00" =>
 #               sh1 := r.addr(42 downto 12);
-            with m.Case(0):
+            with m.Case(Const(0b00, 2)):
                 comb += sh1.eq(r.addr[12:43])
 #           when "01" =>
 #               sh1 := r.addr(58 downto 28);
-            with m.Case(1):
+            with m.Case(Const(0b01, 2)):
                 comb += sh1.eq(r.addr[28:59])
 #           when others =>
 #               sh1 := "0000000000000" & r.addr(61 downto 44);
             with m.Default():
-                comb += sh1.eq(r.addr[44:62])
+                comb += sh1.eq(Cat(r.addr[44:62],
+                               Const(0b0000000000000, 13))
 #       end case;
 
 #       case r.shift(3 downto 2) is
         with m.Switch(r.shift[2:4]):
 #           when "00" =>
 #               sh2 := sh1(18 downto 0);
-            with m.Case(0):
+            with m.Case(Const(0b00, 2)):
                 comb += sh2.eq(sh1[0:19])
 #           when "01" =>
 #               sh2 := sh1(22 downto 4);
-            with m.Case(1):
+            with m.Case(Const(0b01, 2)):
                 comb += sh2.eq(sh1[4:23])
 #           when "10" =>
 #               sh2 := sh1(26 downto 8);
-            with m.Case(2):
+            with m.Case(Const(0b10, 2)):
                 comb += sh2.eq(sh1[8:27])
 #           when others =>
 #               sh2 := sh1(30 downto 12);
@@ -290,15 +300,15 @@ class AddrShifter(Elaboratable):
         with m.Switch(r.shift[0:2]):
 #           when "00" =>
 #               result := sh2(15 downto 0);
-            with m.Case(0):
+            with m.Case(Const(0b00, 2)):
                 comb += result.eq(sh1[0:16])
 #           when "01" =>
 #               result := sh2(16 downto 1);
-            with m.Case(1):
+            with m.Case(Const(0b01, 2)):
                 comb += result.eq(sh1[1:17])
 #           when "10" =>
 #               result := sh2(17 downto 2);
-            with m.Case(2):
+            with m.Case(Const(0b10, 2)):
                 comb += result.eq(sh1[2:18])
 #           when others =>
 #               result := sh2(18 downto 3);
@@ -306,16 +316,19 @@ class AddrShifter(Elaboratable):
                 comb += result.eq(sh1[3:19])
 #       end case;
 #       addrsh <= result;
-        comb += self.addrsh.eq(result)
+        comb += addrsh.eq(result)
 #   end process;
 
-#   -- generate mask for extracting address fields for PTE address generation
-#   addrmaskgen: process(all)
-    # generate mask for extracting address fields for PTE address generation
-    class AddrMaskGen(Elaboratable):
+# -- generate mask for extracting address fields for PTE address
+# -- generation
+# addrmaskgen: process(all)
+# generate mask for extracting address fields for PTE address
+# generation
+class AddrMaskGen(Elaboratable, MMU):
     def __init__(self):
 #       variable m : std_ulogic_vector(15 downto 0);
-        self.mask = Signal(16)
+        super().__init__()
+        self.msk = Signal(16)
 
 #   begin
     def elaborate(self, platform):
@@ -326,66 +339,73 @@ class AddrShifter(Elaboratable):
 
         rst = ResetSignal()
 
+        msk = self.msk
+
+        r    = self.r
         mask = self.mask
 
 #       -- mask_count has to be >= 5
 #       m := x"001f";
         # mask_count has to be >= 5
-        comb += mask.eq(0x001F)
+        # TODO check hex conts with lkcl
+        comb += mask.eq(Const(0x001F, 5)
 
 #       for i in 5 to 15 loop
         for i in range(5,16):
 #           if i < to_integer(r.mask_size) then
             with m.If(i < r.mask_size):
 #               m(i) := '1';
-                comb += mask[i].eq(1)
+                comb += msk[i].eq(1)
 #           end if;
 #       end loop;
 #       mask <= m;
-        comb += self.mask.eq(mask)
+        comb += mask.eq(msk)
 #   end process;
-#
-#    -- generate mask for extracting address bits to go in TLB entry
-#    -- in order to support pages > 4kB
-#    finalmaskgen: process(all)
 
-#   generate mask for extracting address bits to go in TLB entry
-#   in order to support pages > 4kB
-    class FinalMaskGen(Elaboratable):
+# -- generate mask for extracting address bits to go in
+# -- TLB entry in order to support pages > 4kB
+# finalmaskgen: process(all)
+# generate mask for extracting address bits to go in
+# TLB entry in order to support pages > 4kB
+class FinalMaskGen(Elaboratable, MMU):
+    def __init__(self):
 #       variable m : std_ulogic_vector(43 downto 0);
-        def __init__(self):
-            self.mask = Signal(44)
-#       begin
-        def elaborate(self, platform):
-            m = Module()
+        super().__init__()
+        self.msk = Signal(44)
 
-            comb = m.d.comb
-            sync = m.d.sync
+#   begin
+    def elaborate(self, platform):
+        m = Module()
 
-            rst = ResetSignal()
+        comb = m.d.comb
+        sync = m.d.sync
 
-            mask = self.mask
+        rst = ResetSignal()
+
+        mask = self.mask
+        r    = self.r
 
-#           m := (others => '0');
-            # TODO value should be vhdl (others => '0') in nmigen
-            comb += mask.eq(0)
+        msk = self.msk
+
+#       m := (others => '0');
+        # TODO value should be vhdl (others => '0') in nmigen
+        comb += msk.eq(0)
 
 #       for i in 0 to 43 loop
         for i in range(44):
 #           if i < to_integer(r.shift) then
             with m.If(i < r.shift):
 #               m(i) := '1';
-                comb += mask.eq(1)
+                comb += msk.eq(1)
 #           end if;
 #       end loop;
 #       finalmask <= m;
         comb += self.finalmask(mask)
 #   end process;
-#
-#   mmu_1: process(all)
-    class MMU1(Elaboratable):
 
-        def __init__(self):
+# mmu_1: process(all)
+class MMU1(Elaboratable):
+    def __init__(self):
 #       variable v : reg_stage_t;
 #       variable dcreq : std_ulogic;
 #       variable tlb_load : std_ulogic;
@@ -500,400 +520,475 @@ class AddrShifter(Elaboratable):
         comb += prtbl_rd.eq(0)
 
 
-#       -- Radix tree data structures in memory are big-endian,
-#       -- so we need to byte-swap them
+#       -- Radix tree data structures in memory are
+#       -- big-endian, so we need to byte-swap them
 #       for i in 0 to 7 loop
-        # Radix tree data structures in memory are big-endian,
-        # so we need to byte-swap them
+        # Radix tree data structures in memory are
+        # big-endian, so we need to byte-swap them
         for i in range(8):
-#           data(i * 8 + 7 downto i * 8) := d_in.data((7 - i)
-#           * 8 + 7 downto (7 - i) * 8);
-            comb += data[i * 8:i * 8 + 7 + 1].eq(d_in.data[
-                         (7 - i) * 8:(7 - i) * 8 + 7 + 1
-                        ])
+#           data(i * 8 + 7 downto i * 8) := d_in.data(
+#                   (7 - i) * 8 + 7 downto (7 - i) * 8);
+            comb += data[i * 8:i * 8 + 7 + 1].eq(
+                         d_in.data[
+                           (7 - i) * 8:(7 - i) * 8 + 7 + 1
+                         ])
 #       end loop;
 
 #       case r.state is
         with m.Switch(r.state):
-#       when IDLE =>
-        with m.Case(State.IDLE):
-#           if l_in.addr(63) = '0' then
-#               pgtbl := r.pgtbl0;
-#               pt_valid := r.pt0_valid;
-            with m.If(l_in.addr[63] == 0):
-                comb += pgtbl.eq(r.pgtbl0)
-                comb += pt_valid.eq(r.pt0_valid)
-#           else
-#               pgtbl := r.pgtbl3;
-#               pt_valid := r.pt3_valid;
-            with m.Else():
-                comb += pgtbl.eq(r.pt3_valid)
-                comb += pt_valid.eq(r.pt3_valid)
-#           end if;
-
-#           -- rts == radix tree size, # address bits being translated
-#           rts := unsigned('0' & pgtbl(62 downto 61) & pgtbl(7 downto 5));
-            # rts == radix tree size, number of address bits being translated
-            comb += rts.eq(((Cat(Const(0b0, 1), Cat(pgtbl[61:63],
-                           pgtbl[5:8]))).as_unsigned())
-
-#           -- mbits == # address bits to index top level of tree
-#           mbits := unsigned('0' & pgtbl(4 downto 0));
-            # mbits == number of address bits to index top level of tree
-            comb += mbits.eq((0 & pgtbl[0:5]).as_unsigned())
-#           -- set v.shift to rts so that we can use finalmask for the
-#           segment check
-#           v.shift := rts;
-#           v.mask_size := mbits(4 downto 0);
-#           v.pgbase := pgtbl(55 downto 8) & x"00";
-            # set v.shift to rts so that we can use finalmask for the segment
-            # check
-            comb += v.shift.eq(rts)
-            comb += v.mask_size.eq(mbits[0:5])
-            comb += v.pgbase.eq(pgtbl[8:56] & 0x00)
-
-#           if l_in.valid = '1' then
-            with m.If(l_in.valid == 1):
-#               v.addr := l_in.addr;
-#               v.iside := l_in.iside;
-#               v.store := not (l_in.load or l_in.iside);
-#               v.priv := l_in.priv;
-                comb += v.addr.eq(l_in.addr
-                comb += v.iside.eq(l_in.iside)
-                comb += v.store.eq(~(l_in.load | l_in.siside))
-#               if l_in.tlbie = '1' then
-                with m.If(l_in.tlbie == 1):
-#                   -- Invalidate all iTLB/dTLB entries for tlbie with
-#                   -- RB[IS] != 0 or RB[AP] != 0, or for slbia
-#                   v.inval_all := l_in.slbia or l_in.addr(11) or l_in.
-#                                  addr(10) or l_in.addr(7) or l_in.addr(6)
-#                                  or l_in.addr(5);
-                    # Invalidate all iTLB/dTLB entries for tlbie with
-                    # RB[IS] != 0 or RB[AP] != 0, or for slbia
-                    comb += v.inval_all.eq(l_in.slbia | l_in.addr[11] |
-                                           l_in.addr[10] | l_in.addr[7] |
-                                           l_in.addr[6] | l_in.addr[5])
-#                   -- The RIC field of the tlbie instruction comes across
-#                   -- on the sprn bus as bits 2--3. RIC=2 flushes process
-#                   -- table caches.
-#                   if l_in.sprn(3) = '1' then
-                    # The RIC field of the tlbie instruction comes across
-                    # on the sprn bus as bits 2--3. RIC=2 flushes process
-                    # table caches.
-                    with m.If(l_in.sprn[3] == 1):
-#                       v.pt0_valid := '0';
-#                       v.pt3_valid := '0';
-                        comb += v.pt0_valid.eq(0)
-                        comb += v.pt3_valid.eq(0)
-#                   end if;
-#                   v.state := DO_TLBIE;
-                    comb += v.state.eq(State.DO_TLBIE)
+#           when IDLE =>
+            with m.Case(State.IDLE):
+#               if l_in.addr(63) = '0' then
+#                   pgtbl := r.pgtbl0;
+#                   pt_valid := r.pt0_valid;
+                with m.If(~l_in.addr[63]):
+                    comb += pgtbl.eq(r.pgtbl0)
+                    comb += pt_valid.eq(r.pt0_valid)
 #               else
+#                   pgtbl := r.pgtbl3;
+#                   pt_valid := r.pt3_valid;
                 with m.Else():
-#                   v.valid := '1';
-                    comb += v.valid.eq(1)
-#                   if pt_valid = '0' then
-                    with m.If(pt_valid == 0):
-#                       -- need to fetch process table entry
-#                       -- set v.shift so we can use finalmask for generating
-#                       -- the process table entry address
-#                       v.shift := unsigned('0' & r.prtbl(4 downto 0));
-#                       v.state := PROC_TBL_READ;
-                        # need to fetch process table entry
-                        # set v.shift so we can use finalmask for generating
-                        # the process table entry address
-                        comb += v.shift.eq((0 & r.prtble[0:5]).as_unsigned())
-                        comb += v.state.eq(State.PROC_TBL_READ)
-
-#                   elsif mbits = 0 then
-                    with m.If(mbits == 0):
-#                       -- Use RPDS = 0 to disable radix tree walks
-#                       v.state := RADIX_FINISH;
-#                       v.invalid := '1';
-                        # Use RPDS = 0 to disable radix tree walks
-                        comb += v.state.eq(State.RADIX_FINISH)
-                        comb += v.invalid.eq(1)
+                    comb += pgtbl.eq(r.pt3_valid)
+                    comb += pt_valid.eq(r.pt3_valid)
+#               end if;
+
+#               -- rts == radix tree size, # address bits being
+#               -- translated
+#               rts := unsigned('0' & pgtbl(62 downto 61) &
+#                       pgtbl(7 downto 5));
+                # rts == radix tree size, number of address bits
+                # being translated
+                comb += rts.eq((Cat(
+                                 Cat(
+                                  pgtbl[5:8],
+                                  pgtbl[61:63]
+                                 ),
+                                 Const(0b0,1)
+                                )).as_unsigned())
+
+#               -- mbits == # address bits to index top level
+#               -- of tree
+#               mbits := unsigned('0' & pgtbl(4 downto 0));
+                # mbits == number of address bits to index top
+                # level of tree
+                comb += mbits.eq((
+                                 Cat(pgtbl[0:5], Const(0b0, 1))
+                                ).as_unsigned())
+#               -- set v.shift to rts so that we can use finalmask
+#               -- for the segment check
+#               v.shift := rts;
+#               v.mask_size := mbits(4 downto 0);
+#               v.pgbase := pgtbl(55 downto 8) & x"00";
+                # set v.shift to rts so that we can use finalmask
+                # for the segment check
+                comb += v.shift.eq(rts)
+                comb += v.mask_size.eq(mbits[0:5])
+                comb += v.pgbase.eq(Cat(
+                                     Cont(0x00, 2),
+                                     pgtbl[8:56]
+                                    ))
+
+#               if l_in.valid = '1' then
+                with m.If(l_in.valid):
+#                   v.addr := l_in.addr;
+#                   v.iside := l_in.iside;
+#                   v.store := not (l_in.load or l_in.iside);
+#                   v.priv := l_in.priv;
+                    comb += v.addr.eq(l_in.addr
+                    comb += v.iside.eq(l_in.iside)
+                    comb += v.store.eq(~(l_in.load | l_in.siside))
+#                   if l_in.tlbie = '1' then
+                    with m.If(l_in.tlbie):
+#                       -- Invalidate all iTLB/dTLB entries for
+#                       -- tlbie with RB[IS] != 0 or RB[AP] != 0,
+#                       -- or for slbia
+#                       v.inval_all := l_in.slbia or l_in.addr(11)
+#                                      or l_in.addr(10) or
+#                                      l_in.addr(7) or l_in.addr(6)
+#                                      or l_in.addr(5);
+                        # Invalidate all iTLB/dTLB entries for
+                        # tlbie with RB[IS] != 0 or RB[AP] != 0,
+                        # or for slbia
+                        comb += v.inval_all.eq(l_in.slbia
+                                               | l_in.addr[11]
+                                               | l_in.addr[10]
+                                               | l_in.addr[7]
+                                               | l_in.addr[6]
+                                               | l_in.addr[5]
+                                              )
+#                       -- The RIC field of the tlbie instruction
+#                       -- comes across on the sprn bus as bits 2--3.
+#                       -- RIC=2 flushes process table caches.
+#                       if l_in.sprn(3) = '1' then
+                        # The RIC field of the tlbie instruction
+                        # comes across on the sprn bus as bits 2--3.
+                        # RIC=2 flushes process table caches.
+                        with m.If(l_in.sprn[3]):
+#                           v.pt0_valid := '0';
+#                           v.pt3_valid := '0';
+                            comb += v.pt0_valid.eq(0)
+                            comb += v.pt3_valid.eq(0)
+#                       end if;
+#                       v.state := DO_TLBIE;
+                        comb += v.state.eq(State.DO_TLBIE)
 #                   else
                     with m.Else():
-#                       v.state := SEGMENT_CHECK;
-                        comb += v.state.eq(State.SEGMENT_CHECK)
+#                       v.valid := '1';
+                        comb += v.valid.eq(1)
+#                       if pt_valid = '0' then
+                        with m.If(~pt_valid):
+#                           -- need to fetch process table entry
+#                           -- set v.shift so we can use finalmask
+#                           -- for generating the process table
+#                           -- entry address
+#                           v.shift := unsigned('0' & r.prtbl(
+#                                               4 downto 0));
+#                           v.state := PROC_TBL_READ;
+                            # need to fetch process table entry
+                            # set v.shift so we can use finalmask
+                            # for generating the process table
+                            # entry address
+                            comb += v.shift.eq((Cat(
+                                               r.prtble[0:5],
+                                               Const(0b0, 1)
+                                              )).as_unsigned())
+                            comb += v.state.eq(State.PROC_TBL_READ)
+
+#                       elsif mbits = 0 then
+                        with m.If(~mbits):
+#                           -- Use RPDS = 0 to disable radix
+#                           -- tree walks
+#                           v.state := RADIX_FINISH;
+#                           v.invalid := '1';
+                            # Use RPDS = 0 to disable radix
+                            # tree walks
+                            comb += v.state.eq(State.RADIX_FINISH)
+                            comb += v.invalid.eq(1)
+#                       else
+                        with m.Else():
+#                           v.state := SEGMENT_CHECK;
+                            comb += v.state.eq(State.SEGMENT_CHECK)
+#                       end if;
 #                   end if;
 #               end if;
-#           end if;
 
-#           if l_in.mtspr = '1' then
-            with m.If(l_in.mtspr == 1):
-#               -- Move to PID needs to invalidate L1 TLBs and cached
-#               -- pgtbl0 value.  Move to PRTBL does that plus
-#               -- invalidating the cached pgtbl3 value as well.
-#               if l_in.sprn(9) = '0' then
-                # Move to PID needs to invalidate L1 TLBs and cached
-                # pgtbl0 value.  Move to PRTBL does that plus
-                # invalidating the cached pgtbl3 value as well.
-                with m.If(l_in.sprn[9] == 0):
-#                   v.pid := l_in.rs(31 downto 0);
-                    comb += v.pid.eq(l_in.rs[0:32])
-#               else
-                with m.Else():
-#                   v.prtbl := l_in.rs;
-#                   v.pt3_valid := '0';
-                    comb += v.prtbl.eq(l_in.rs)
-                    comb += v.pt3_valid.eq(0)
-#               end if;
+#               if l_in.mtspr = '1' then
+                with m.If(l_in.mtspr):
+#                   -- Move to PID needs to invalidate L1 TLBs
+#                   -- and cached pgtbl0 value.  Move to PRTBL
+#                   -- does that plus invalidating the cached
+#                   -- pgtbl3 value as well.
+#                   if l_in.sprn(9) = '0' then
+                    # Move to PID needs to invalidate L1 TLBs
+                    # and cached pgtbl0 value.  Move to PRTBL
+                    # does that plus invalidating the cached
+                    # pgtbl3 value as well.
+                    with m.If(~l_in.sprn[9]):
+#                       v.pid := l_in.rs(31 downto 0);
+                        comb += v.pid.eq(l_in.rs[0:32])
+#                   else
+                    with m.Else():
+#                       v.prtbl := l_in.rs;
+#                       v.pt3_valid := '0';
+                        comb += v.prtbl.eq(l_in.rs)
+                        comb += v.pt3_valid.eq(0)
+#                   end if;
 
-#               v.pt0_valid := '0';
-#               v.inval_all := '1';
-#               v.state := DO_TLBIE;
-                comb += v.pt0_valid.eq(0)
-                comb += v.inval_all.eq(0)
-                comb += v.state.eq(State.DO_TLBIE)
-#           end if;
+#                   v.pt0_valid := '0';
+#                   v.inval_all := '1';
+#                   v.state := DO_TLBIE;
+                    comb += v.pt0_valid.eq(0)
+                    comb += v.inval_all.eq(0)
+                    comb += v.state.eq(State.DO_TLBIE)
+#               end if;
 
 #       when DO_TLBIE =>
-        with m.Case(State.DO_TLBIE):
-#           dcreq := '1';
-#           tlbie_req := '1';
-#           v.state := TLB_WAIT;
-            comb += dcreq.eq(1)
-            comb += tlbie_req.eq(1)
-            comb += v.state.eq(State.TLB_WAIT)
+            with m.Case(State.DO_TLBIE):
+#               dcreq := '1';
+#               tlbie_req := '1';
+#               v.state := TLB_WAIT;
+                comb += dcreq.eq(1)
+                comb += tlbie_req.eq(1)
+                comb += v.state.eq(State.TLB_WAIT)
 
 #       when TLB_WAIT =>
-        with m.Case(State.TLB_WAIT):
-#           if d_in.done = '1' then
-            with m.If(d_in.done == 1):
-#               v.state := RADIX_FINISH;
-                comb += v.state.eq(State.RADIX_FINISH)
-#           end if;
+            with m.Case(State.TLB_WAIT):
+#               if d_in.done = '1' then
+                with m.If(d_in.done):
+#                   v.state := RADIX_FINISH;
+                    comb += v.state.eq(State.RADIX_FINISH)
+#               end if;
 
 #       when PROC_TBL_READ =>
-        with m.Case(State.PROC_TBL_READ):
+            with m.Case(State.PROC_TBL_READ):
 #           dcreq := '1';
 #           prtbl_rd := '1';
 #           v.state := PROC_TBL_WAIT;
-            comb += dcreq.eq(1)
-            comb += prtbl_rd.eq(1)
-            comb += v.state.eq(State.PROC_TBL_WAIT)
+                comb += dcreq.eq(1)
+                comb += prtbl_rd.eq(1)
+                comb += v.state.eq(State.PROC_TBL_WAIT)
 
 #       when PROC_TBL_WAIT =>
-        with m.Case(State.PROC_TBL_WAIT):
+            with m.Case(State.PROC_TBL_WAIT):
 #           if d_in.done = '1' then
-            with m.If(d_in.done == 1):
+                with m.If(d_in.done):
 #               if r.addr(63) = '1' then
-                with m.If(r.addr[63] == 1):
+                    with m.If(r.addr[63]):
 #                   v.pgtbl3 := data;
 #                   v.pt3_valid := '1';
-                    comb += v.pgtbl3.eq(data)
-                    comb += v.pt3_valid.eq(1)
-#               else
-                with m.Else():
-#                   v.pgtbl0 := data;
-#                   v.pt0_valid := '1';
-                    comb += v.pgtbl0.eq(data)
-                    comb += v.pt0_valid.eq(1)
-#               end if;
-#               -- rts == radix tree size, # address bits being translated
-#               rts := unsigned('0' & data(62 downto 61) & data(7 downto 5));
-                # rts == radix tree size, # address bits being translated
-                comb += rts.eq((0 & data[61:63] & data[5:8]).as_unsigned())
-#               -- mbits == # address bits to index top level of tree
-#               mbits := unsigned('0' & data(4 downto 0));
-                # mbits == # address bits to index top level of tree
-                comb += mbits.eq((0 & data[0:5]).as_unsigned())
-#               -- set v.shift to rts so that we can use finalmask for the
-#               -- segment check
+                        comb += v.pgtbl3.eq(data)
+                        comb += v.pt3_valid.eq(1)
+#                   else
+                    with m.Else():
+#                       v.pgtbl0 := data;
+#                       v.pt0_valid := '1';
+                        comb += v.pgtbl0.eq(data)
+                        comb += v.pt0_valid.eq(1)
+#                   end if;
+#                   -- rts == radix tree size, # address bits
+#                   -- being translated
+#                   rts := unsigned('0' & data(62 downto 61) &
+#                                   data(7 downto 5));
+                    # rts == radix tree size, # address bits
+                    # being translated
+                    comb += rts.eq((
+                                   0 & data[61:63] & data[5:8]
+                                  ).as_unsigned())
+#                   -- mbits == # address bits to index
+#                   -- top level of tree
+#                   mbits := unsigned('0' & data(4 downto 0));
+                    # mbits == # address bits to index
+                    # top level of tree
+                    comb += mbits.eq((
+                                     0 & data[0:5]
+                                    ).as_unsigned())
+#               -- set v.shift to rts so that we can use
+#               -- finalmask for the segment check
 #               v.shift := rts;
 #               v.mask_size := mbits(4 downto 0);
 #               v.pgbase := data(55 downto 8) & x"00";
-                # set v.shift to rts so that we can use finalmask for the
-                # segment check
-                comb += v.shift.eq(rts)
-                comb += v.mask_size.eq(mbits[0:5])
-                comb += v.pgbase.eq(data[8:56] & 0x00)
-#               if mbits = 0 then
-                with m.If(mbits == 0):
+                    # set v.shift to rts so that we can use
+                    # finalmask for the segment check
+                    comb += v.shift.eq(rts)
+                    comb += v.mask_size.eq(mbits[0:5])
+                    comb += v.pgbase.eq(data[8:56] & 0x00)
+#                   if mbits = 0 then
+                    with m.If(~mbits):
+#                       v.state := RADIX_FINISH;
+#                       v.invalid := '1';
+                        comb += v.state.eq(State.RADIX_FINISH)
+                        comb += v.invalid.eq(1)
+#                   else
+#                       v.state := SEGMENT_CHECK;
+                        comb += v.state.eq(State.SEGMENT_CHECK)
+#                   end if;
+#               end if;
+
+#               if d_in.err = '1' then
+                with m.If(d_in.err === 1):
 #                   v.state := RADIX_FINISH;
-#                   v.invalid := '1';
+#                   v.badtree := '1';
                     comb += v.state.eq(State.RADIX_FINISH)
-                    comb += v.invalid.eq(1)
-#               else
-#                   v.state := SEGMENT_CHECK;
-                    comb += v.state.eq(State.SEGMENT_CHECK)
+                    comb += v.badtree.eq(1)
 #               end if;
-#           end if;
-
-#           if d_in.err = '1' then
-            with m.If(d_in.err === 1):
-#               v.state := RADIX_FINISH;
-#               v.badtree := '1';
-                comb += v.state.eq(State.RADIX_FINISH)
-                comb += v.badtree.eq(1)
-#           end if;
 
-#       when SEGMENT_CHECK =>
-        with m.Case(State.SEGMENT_CHECK):
-#           mbits := '0' & r.mask_size;
-#           v.shift := r.shift + (31 - 12) - mbits;
-#           nonzero := or(r.addr(61 downto 31) and not finalmask(
-#                      30 downto 0));
-            comb += mbits.eq(0 & r.mask_size)
-            comb += v.shift.eq(r.shift + (31 -12) - mbits)
-            comb += nonzero.eq('''TODO wrap in or (?)'''r.addr[31:62]
-                               & (~finalmask[0:31]))
-#           if r.addr(63) /= r.addr(62) or nonzero = '1' then
-#               v.state := RADIX_FINISH;
-#               v.segerror := '1';
-            with m.If((r.addr[63] != r.addr[62]) | (nonzero == 1)):
-                comb += v.state.eq(State.RADIX_FINISH)
-                comb += v.segerror.eq(1)
-#           elsif mbits < 5 or mbits > 16 or mbits >
-#           (r.shift + (31 - 12)) then
-#               v.state := RADIX_FINISH;
-#               v.badtree := '1';
-            with m.If((mbits < 5) | (mbits > 16)
-                      | (mbits > (r.shift + (31-12)))):
-                comb += v.state.eq(State.RADIX_FINISH)
-                comb += v.badtree.eq(1)
+#           when SEGMENT_CHECK =>
+            with m.Case(State.SEGMENT_CHECK):
+#               mbits := '0' & r.mask_size;
+#               v.shift := r.shift + (31 - 12) - mbits;
+#               nonzero := or(r.addr(61 downto 31) and
+#                           not finalmask(30 downto 0));
+                comb += mbits.eq(0 & r.mask_size)
+                comb += v.shift.eq(r.shift + (31 -12) - mbits)
+                # TODO need lckl to check this is correct
+                comb += nonzero.eq(0 | Cat((~finalmask[0:31]),
+                                   r.addr[31:62]
+                                  ))
+#               if r.addr(63) /= r.addr(62) or nonzero = '1' then
+#                   v.state := RADIX_FINISH;
+#                   v.segerror := '1';
+                with m.If((r.addr[63] != r.addr[62])
+                          | (nonzero == 1)):
+                    comb += v.state.eq(State.RADIX_FINISH)
+                    comb += v.segerror.eq(1)
+#               elsif mbits < 5 or mbits > 16 or mbits
+#                       > (r.shift + (31 - 12)) then
+#                   v.state := RADIX_FINISH;
+#                   v.badtree := '1';
+                with m.If((mbits < 5) | (mbits > 16)
+                          | (mbits > (r.shift + (31-12)))):
+                    comb += v.state.eq(State.RADIX_FINISH)
+                    comb += v.badtree.eq(1)
 #           else
 #               v.state := RADIX_LOOKUP;
-            with m.Else():
-                comb += v.state.eq(State.RADIX_LOOKUP)
+                with m.Else():
+                    comb += v.state.eq(State.RADIX_LOOKUP)
 #           end if;
 #
-#       when RADIX_LOOKUP =>
-        with m.Case(State.RADIX_LOOKUP):
-#           dcreq := '1';
-#           v.state := RADIX_READ_WAIT;
-            comb += dcreq.eq(1)
-            comb += v.state.eq(State.RADIX_READ_WAIT)
+#           when RADIX_LOOKUP =>
+            with m.Case(State.RADIX_LOOKUP):
+#               dcreq := '1';
+#               v.state := RADIX_READ_WAIT;
+                comb += dcreq.eq(1)
+                comb += v.state.eq(State.RADIX_READ_WAIT)
+
+#           when RADIX_READ_WAIT =>
+            with m.Case(State.RADIX_READ_WAIT):
+#               if d_in.done = '1' then
+                with m.If(d_in.done):
+#                   v.pde := data;
+                    comb += v.pde.eq(data)
+#                   -- test valid bit
+#                   if data(63) = '1' then
+                    # test valid bit
+                    with m.If(data[63]):
+#                       -- test leaf bit
+#                       if data(62) = '1' then
+                        # test leaf bit
+                        with m.If(data[62]):
+#                           -- check permissions and RC bits
+#                           perm_ok := '0';
+                            comb += perm_ok.eq(0)
+#                           if r.priv = '1' or data(3) = '0' then
+                            with m.If((r.priv == 1) | (data[3] == 0)):
+#                               if r.iside = '0' then
+#                                   perm_ok := data(1) or (data(2)
+#                                              and not r.store);
+                                with m.If(r.iside == 0):
+                                    comb += perm_ok.eq(
+                                              (data[1] | data[2])
+                                              & (~r.store)
+                                            )
+#                               else
+                                with m.Else():
+#                                   -- no IAMR, so no KUEP support
+#                                   -- for now deny execute
+#                                   -- permission if cache inhibited
+#                                   perm_ok :=
+#                                       data(0) and not data(5);
+                                    # no IAMR, so no KUEP support
+                                    # for now deny execute
+                                    # permission if cache inhibited
+                                    comb += perm_ok.eq(
+                                              data[0] & (~data[5])
+                                            )
+#                               end if;
+#                           end if;
 
-#       when RADIX_READ_WAIT =>
-        with m.Case(State.RADIX_READ_WAIT):
-#           if d_in.done = '1' then
-            with m.If(d_in.done == 1):
-#               v.pde := data;
-                comb += v.pde.eq(data)
-#               -- test valid bit
-#               if data(63) = '1' then
-                # test valid bit
-                with m.If(data[63] == 1):
-#                   -- test leaf bit
-#                   if data(62) = '1' then
-                    # test leaf bit
-                    with m.If(data[62] == 1):
-#                       -- check permissions and RC bits
-#                       perm_ok := '0';
-                        comb += perm_ok.eq(0)
-#                       if r.priv = '1' or data(3) = '0' then
-                        with m.If((r.priv == 1) | (data[3] == 0)):
-#                           if r.iside = '0' then
-#                               perm_ok := data(1) or (data(2) and not
-#                                          r.store);
-                            with m.If(r.iside == 0):
-                                comb += perm_ok.eq((data[1] | data[2])
-                                                   & (~r.store))
+#                           rc_ok := data(8) and (data(7) or
+#                                    not r.store);
+                            comb += rc_ok.eq(
+                                      data[8] &
+                                      (data[7] | (~r.store))
+                                    )
+#                           if perm_ok = '1' and rc_ok = '1' then
+#                               v.state := RADIX_LOAD_TLB;
+                            with m.If(perm_ok & rc_ok):
+                                comb += v.state.eq(
+                                          State.RADIX_LOAD_TLB
+                                        )
 #                           else
                             with m.Else():
-#                               -- no IAMR, so no KUEP support for now
-#                               -- deny execute permission if cache inhibited
-#                               perm_ok := data(0) and not data(5);
-                                # no IAMR, so no KUEP support for now
-                                # deny execute permission if cache inhibited
-                                comb += perm_ok.eq(data[0] & (~data[5]))
+#                           v.state := RADIX_FINISH;
+#                           v.perm_err := not perm_ok;
+#                           -- permission error takes precedence
+#                           -- over RC error
+#                               v.rc_error := perm_ok;
+                                comb += vl.state.eq(
+                                          State.RADIX_FINISH
+                                        )
+                                comb += v.perm_err.eq(~perm_ok)
+                                # permission error takes precedence
+                                # over RC error
+                                comb += v.rc_error.eq(perm_ok)
 #                           end if;
-#                       end if;
-
-#                       rc_ok := data(8) and (data(7) or not r.store);
-                        comb += rc_ok.eq(data[8] & (data[7] | (~r.store)))
-#                       if perm_ok = '1' and rc_ok = '1' then
-#                           v.state := RADIX_LOAD_TLB;
-                        with m.If(perm_ok == 1 & rc_ok == 1):
-                            comb += v.state.eq(State.RADIX_LOAD_TLB)
 #                       else
                         with m.Else():
-#                           v.state := RADIX_FINISH;
-#                           v.perm_err := not perm_ok;
-#                           -- permission error takes precedence over
-#                           -- RC error
-#                           v.rc_error := perm_ok;
-                            comb += vl.state.eq(State.RADIX_FINISH)
-                            comb += v.perm_err.eq(~perm_ok)
-                            # permission error takes precedence over
-                            # RC error
-                            comb += v.rc_error.eq(perm_ok)
+#                           mbits := unsigned('0' &
+#                                    data(4 downto 0));
+                            comb += mbits.eq((Cat(
+                                      data[0:5]
+                                      Cont(0b0,1)
+                                    )).as_unsigned())
+#                           if mbits < 5 or mbits > 16 or
+#                           mbits > r.shift then
+#                               v.state := RADIX_FINISH;
+#                               v.badtree := '1';
+                            with m.If((mbits < 5) & (mbits > 16) |
+                                      (mbits > r.shift)):
+                                comb += v.state.eq(
+                                          State.RADIX_FINISH
+                                        )
+                                comb += v.badtree.eq(1)
+#                           else
+                            with m.Else():
+#                               v.shift := v.shift - mbits;
+#                               v.mask_size := mbits(4 downto 0);
+#                               v.pgbase := data(55 downto 8)
+#                                           & x"00";
+#                               v.state := RADIX_LOOKUP;
+                                comb += v.shift.eq(v.shif - mbits)
+                                comb += v.mask_size.eq(mbits[0:5])
+                                comb += v.pgbase.eq(Cat(
+                                          Const(0x00, 2),
+                                          mbits[8:56])
+                                        )
+                                comb += v.state.eq(
+                                          State.RADIX_LOOKUP
+                                        )
+#                           end if;
 #                       end if;
 #                   else
                     with m.Else():
-#                       mbits := unsigned('0' & data(4 downto 0));
-                        comb += mbits.eq((0 & data[0:5]).as_unsigned())
-#                       if mbits < 5 or mbits > 16 or mbits > r.shift then
-#                           v.state := RADIX_FINISH;
-#                           v.badtree := '1';
-                        with m.If((mbits < 5) & (mbits > 16) |
-                                  (mbits > r.shift)):
-                            comb += v.state.eq(State.RADIX_FINISH)
-                            comb += v.badtree.eq(1)
-#                       else
-                        with m.Else():
-#                           v.shift := v.shift - mbits;
-#                           v.mask_size := mbits(4 downto 0);
-#                           v.pgbase := data(55 downto 8) & x"00";
-#                           v.state := RADIX_LOOKUP;
-                            comb += v.shift.eq(v.shif - mbits)
-                            comb += v.mask_size.eq(mbits[0:5])
-                            comb += v.pgbase.eq(mbits[8:56] & 0x00)
-                            comb += v.state.eq(State.RADIX_LOOKUP)
-#                       end if;
+#                       -- non-present PTE, generate a DSI
+#                       v.state := RADIX_FINISH;
+#                       v.invalid := '1';
+                        # non-present PTE, generate a DSI
+                        comb += v.state.eq(State.RADIX_FINISH)
+                        comb += v.invalid.eq(1)
 #                   end if;
-#               else
-                with m.Else():
-#                   -- non-present PTE, generate a DSI
+#               end if;
+
+#               if d_in.err = '1' then
+                with m.If(d_in.err):
 #                   v.state := RADIX_FINISH;
-#                   v.invalid := '1';
-                    # non-present PTE, generate a DSI
+#                   v.badtree := '1';
                     comb += v.state.eq(State.RADIX_FINISH)
-                    comb += v.invalid.eq(1)
+                    comb += v.badtree.eq(1)
 #               end if;
-#           end if;
 
-#           if d_in.err = '1' then
-            with m.If(d_in.err == 1):
-#               v.state := RADIX_FINISH;
-#               v.badtree := '1';
-                comb += v.state.eq(State.RADIX_FINISH)
-                comb += v.badtree.eq(1)
-#           end if;
+#           when RADIX_LOAD_TLB =>
+            with m.Case(State.RADIX_LOAD_TLB):
+#               tlb_load := '1';
+                comb +=  tlb_load.eq(1)
+#               if r.iside = '0' then
+                with m.If(~r.iside):
+#                   dcreq := '1';
+#                   v.state := TLB_WAIT;
+                    comb += dcreq.eq(1)
+                    comb += v.state.eq(State.TLB_WAIT)
+#               else
+                with m.Else():
+#                   itlb_load := '1';
+#                   v.state := IDLE;
+                    comb += itlb_load.eq(1)
+                    comb += v.state.eq(State.IDLE)
+#               end if;
 
-#       when RADIX_LOAD_TLB =>
-        with m.Case(State.RADIX_LOAD_TLB):
-#           tlb_load := '1';
-            comb +=  tlb_load.eq(1)
-#           if r.iside = '0' then
-            with m.If(r.iside == 0):
-#               dcreq := '1';
-#               v.state := TLB_WAIT;
-                comb += dcreq.eq(1)
-                comb += v.state.eq(State.TLB_WAIT)
-#           else
-            with m.Else():
-#               itlb_load := '1';
+#           when RADIX_FINISH =>
 #               v.state := IDLE;
-                comb += itlb_load.eq(1)
+            with m.Case(State.RADIX_FINISH):
+#               v.state := IDLE
                 comb += v.state.eq(State.IDLE)
-#           end if;
-
-#       when RADIX_FINISH =>
-#           v.state := IDLE;
-        with m.Case(State.RADIX_FINISH):
-            comb += v.state.eq(State.IDLE)
 #       end case;
 #
 #       if v.state = RADIX_FINISH or (v.state = RADIX_LOAD_TLB
 #       and r.iside = '1') then
-        with m.If(v.state == State.RADIX_FINISH | (v.state ==
-                  State.RADIX_LOAD_TLB & r.iside == 1))
-#           v.err := v.invalid or v.badtree or v.segerror or v.perm_err
-#           or v.rc_error;
+        with m.If(v.state == State.RADIX_FINISH
+                  | (v.state == State.RADIX_LOAD_TLB & r.iside)
+                 )
+#           v.err := v.invalid or v.badtree or v.segerror
+#                    or v.perm_err or v.rc_error;
 #           v.done := not v.err;
             comb += v.err.eq(v.invalid | v.badtree | v.segerror
                              | v.perm_err | v.rc_error)
@@ -901,12 +996,12 @@ class AddrShifter(Elaboratable):
 #       end if;
 
 #       if r.addr(63) = '1' then
+        with m.If(r.addr[63]):
 #           effpid := x"00000000";
-        with m.If(r.addr[63] == 1):
-            comb += effpid.eq(0x00000000)
+            comb += effpid.eq(Const(0x00000000,1))
 #       else
-#           effpid := r.pid;
         with m.Else():
+#           effpid := r.pid;
             comb += effpid.eq(r.pid)
 #       end if;
 #       prtable_addr := x"00" & r.prtbl(55 downto 36) &
@@ -914,42 +1009,73 @@ class AddrShifter(Elaboratable):
 #                       23 downto 0)) or (effpid(31 downto 8) and
 #                       finalmask(23 downto 0))) & effpid(7 downto 0)
 #                       & "0000";
-        comb += prtable_addr.eq(0x00 & r.prtble[36:56] &
-                                ((r.prtble[12:36] & (~finalmask[0:24]))
-                                | effpid[8:32] & finalmask[0:24])
-                                & effpid[0:8] & 0x0000)
+        comb += prtable_addr.eq(
+                 Cat(
+                  Cat(
+                   Cat(
+                    Cat(Const(0b000, 4), effpid[0:8]),
+                    (
+                     (r.prtble[12:36] & (~finalmask[0:24]))
+                     | effpid[8:32] & finalmask[0:24]
+                    )
+                   ),
+                   r.prtbl[36:56]
+                  ),
+                  Const(0x00, 2)
+                 )
+                )
 
 #       pgtable_addr := x"00" & r.pgbase(55 downto 19) &
 #                       ((r.pgbase(18 downto 3) and not mask) or
 #                       (addrsh and mask)) & "000";
-        comb += pgtable_addr.eq(0x00 & r.pgbase[19:56] & ((r.pgbase[3:19]
-                                & (~mask)) | (addrsh & mask)) & 0x000)
+        comb += pgtable_addr.eq(
+                 Cat(
+                  Cat(
+                   Const(0b000, 3),
+                   (
+                    (r.pgbase[3:19] & (~mask))
+                    | (addrsh & mask)
+                   )
+                  ),
+                  Const(0x00, 2)
+                 )
+                )
 
 #       pte := x"00" & ((r.pde(55 downto 12) and not finalmask) or
 #              (r.addr(55 downto 12) and finalmask)) & r.pde(11 downto 0);
-        comb += pte.eq(0x00 & ((r.pde[12:56] & (~finalmask))
-                       | (r.addr[12:56] & finalmask)) & r.pde[0:12])
+        comb += pte.eq(
+                 Cat(
+                  Cat(
+                   r.pde[0:12],
+                   (
+                    (r.pde[12:56] & (~finalmask))
+                    | (r.addr[12:56] & finalmask)
+                   )
+                  ),
+                  Const(0x00, 2)
+                 )
+                )
 
 #       -- update registers
 #       rin <= v;
         # update registers
-        rin.eq(v
-               )
+        rin.eq(v)
+
 #       -- drive outputs
 #       if tlbie_req = '1' then
         # drive outputs
-        with m.If(tlbie_req == 1):
+        with m.If(tlbie_req):
 #           addr := r.addr;
 #           tlb_data := (others => '0');
             comb += addr.eq(r.addr)
             comb += tlb_data.eq('''TODO ()others => '0') ''')
 #       elsif tlb_load = '1' then
-        with m.If(tlb_load == 1):
+        with m.If(tlb_load):
 #           addr := r.addr(63 downto 12) & x"000";
 #           tlb_data := pte;
-            comb += addr.eq(r.addr[12:64] & 0x000)
+            comb += addr.eq(Cat(Const(0x000, 3), r.addr[12:64]))
 #       elsif prtbl_rd = '1' then
-        with m.If(prtbl_rd == 1):
+        with m.If(prtbl_rd):
 #           addr := prtable_addr;
 #           tlb_data := (others => '0');
             comb += addr.eq(prtable_addr)
@@ -1002,4 +1128,4 @@ class AddrShifter(Elaboratable):
         comb += i_out.pte.eq(tlb_data)
 
 #   end process;
-#end;
+# end;