1 from nmigen
import Elaboratable
, Module
, Record
, Const
3 from .dmi
import (DebugReg
, DmiOp
, RegMode
,
4 abstractcs_layout
, cmd_access_reg_layout
, command_layout
,
5 dmcontrol_layout
, dmstatus_layout
, flat_layout
, sbcs_layout
)
8 __all__
= ["DebugRegisterFile"]
24 DebugReg
.DMSTATUS
: dmstatus_layout
,
25 DebugReg
.DMCONTROL
: dmcontrol_layout
,
26 DebugReg
.HARTINFO
: flat_layout
,
27 DebugReg
.ABSTRACTCS
: abstractcs_layout
,
28 DebugReg
.COMMAND
: command_layout
,
29 DebugReg
.SBCS
: sbcs_layout
,
30 DebugReg
.SBADDRESS0
: flat_layout
,
31 DebugReg
.SBDATA0
: flat_layout
,
32 DebugReg
.DATA0
: flat_layout
36 class DebugRegisterFile(Elaboratable
):
37 def __init__(self
, dmi
):
41 def reg_port(self
, addr
):
42 if addr
not in reg_map
:
43 raise ValueError("Unknown register {:x}.".format(addr
))
44 if addr
in self
.ports
:
45 raise ValueError("Register {:x} has already been allocated.".format(addr
))
46 layout
= [f
[:2] for f
in reg_map
[addr
]]
47 port
= Record([("r", layout
), ("w", layout
), ("update", 1), ("capture", 1)])
48 for name
, shape
, mode
, reset
in reg_map
[addr
]:
49 getattr(port
.r
, name
).reset
= reset
50 getattr(port
.w
, name
).reset
= reset
51 self
.ports
[addr
] = port
54 def elaborate(self
, platform
):
57 def do_read(addr
, port
):
58 rec
= Record(port
.w
.layout
)
59 m
.d
.sync
+= self
.dmi
.r
.data
.eq(rec
)
60 for name
, shape
, mode
, reset
in reg_map
[addr
]:
61 dst
= getattr(rec
, name
)
62 src
= getattr(port
.w
, name
)
63 if mode
in {RegMode
.R
, RegMode
.RW
, RegMode
.RW1C
}:
64 m
.d
.comb
+= dst
.eq(src
)
66 m
.d
.comb
+= dst
.eq(Const(0))
67 m
.d
.sync
+= port
.capture
.eq(1)
69 def do_write(addr
, port
):
70 rec
= Record(port
.r
.layout
)
71 m
.d
.comb
+= rec
.eq(self
.dmi
.w
.data
)
72 for name
, shape
, mode
, reset
in reg_map
[addr
]:
73 dst
= getattr(port
.r
, name
)
74 src
= getattr(rec
, name
)
75 if mode
in {RegMode
.W
, RegMode
.RW
}:
76 m
.d
.sync
+= dst
.eq(src
)
77 elif mode
is RegMode
.W1
:
78 m
.d
.sync
+= dst
.eq(getattr(port
.w
, name
) | src
)
79 elif mode
is RegMode
.RW1C
:
80 m
.d
.sync
+= dst
.eq(getattr(port
.w
, name
) & ~src
)
82 m
.d
.sync
+= port
.update
.eq(1)
84 with m
.If(self
.dmi
.update
):
85 with m
.Switch(self
.dmi
.w
.addr
):
86 for addr
, port
in self
.ports
.items():
88 with m
.If(self
.dmi
.w
.op
== DmiOp
.READ
):
90 with m
.Elif(self
.dmi
.w
.op
== DmiOp
.WRITE
):
92 m
.d
.sync
+= self
.dmi
.r
.op
.eq(DmiResult
.OK
)
95 m
.d
.sync
+= self
.dmi
.r
.op
.eq(DmiResult
.FAIL
)
97 for port
in self
.ports
.values():
98 with m
.If(port
.update
):
99 m
.d
.sync
+= port
.update
.eq(0)
100 with m
.If(port
.capture
):
101 m
.d
.sync
+= port
.capture
.eq(0)