radix: reading first page table entry
[soc.git] / src / soc / debug / firmware_upload.py
1 """JTAG Wishbone firmware upload program
2
3 to test, run "python3 debug/test/test_jtag_tap_srv.py server"
4
5 """
6
7 import sys
8 from nmigen import (Module, Signal, Elaboratable, Const)
9 from c4m.nmigen.jtag.tap import TAP, IOType
10 from c4m.nmigen.jtag.bus import Interface as JTAGInterface
11 from soc.debug.dmi import DMIInterface, DBGCore, DBGStat, DBGCtrl
12 from soc.debug.test.dmi_sim import dmi_sim
13 from soc.debug.jtag import JTAG
14 from soc.debug.test.jtagremote import JTAGServer, JTAGClient
15
16 from nmigen_soc.wishbone.sram import SRAM
17 from nmigen import Memory, Signal, Module
18
19 from nmigen.back.pysim import Simulator, Delay, Settle, Tick
20 from nmutil.util import wrap
21 from soc.debug.jtagutils import (jtag_read_write_reg,
22 jtag_srv, jtag_set_reset,
23 jtag_set_ir, jtag_set_get_dr)
24
25 def test_pinset():
26 return {
27 # in, out, tri-out, tri-inout
28 'test': ['io0-', 'io1+', 'io2>', 'io3*'],
29 }
30
31
32 # JTAG-ircodes for accessing DMI
33 DMI_ADDR = 8
34 DMI_READ = 9
35 DMI_WRRD = 10
36
37 # JTAG-ircodes for accessing Wishbone
38 WB_ADDR = 5
39 WB_READ = 6
40 WB_WRRD = 7
41
42
43 def read_dmi_addr(dut, dmi_addr):
44 # write DMI address
45 yield from jtag_read_write_reg(dut, DMI_ADDR, 8, dmi_addr)
46
47 # read DMI register
48 return (yield from jtag_read_write_reg(dut, DMI_READ, 64))
49
50 def writeread_dmi_addr(dut, dmi_addr, data):
51 # write DMI address
52 yield from jtag_read_write_reg(dut, DMI_ADDR, 8, dmi_addr)
53
54 # write and read DMI register
55 return (yield from jtag_read_write_reg(dut, DMI_WRRD, 64, data))
56
57
58 def jtag_sim(dut, firmware):
59 """uploads firmware with the following commands:
60 * read IDcode (to check)
61 * set "stopped" and reset
62 * repeat until confirmed "stopped"
63 * upload data over wishbone
64 * read data back and check it
65 * issue cache flush command
66 * issue "start" command
67 """
68
69 ####### JTAGy stuff (IDCODE) ######
70
71 # read idcode
72 yield from jtag_set_reset(dut)
73 idcode = yield from jtag_read_write_reg(dut, 0b1, 32)
74 print ("idcode", hex(idcode))
75 assert idcode == 0x18ff
76
77 ####### JTAG to DMI Setup (stop, reset) ######
78
79 yield from read_dmi_addr(dut, DBGCore.CTRL)
80 # read DMI CTRL reg
81 status = yield from read_dmi_addr(dut, DBGCore.CTRL)
82 print ("dmi ctrl status", bin(status))
83
84 # write DMI CTRL register - STOP and RESET
85 status = yield from writeread_dmi_addr(dut, DBGCore.CTRL, 0b011)
86 print ("dmi ctrl status", hex(status))
87 assert status == 4 # returned old value (nice! cool feature!)
88
89 # read STAT and wait for "STOPPED"
90 while True:
91 status = yield from read_dmi_addr(dut, DBGCore.STAT)
92 print ("dmi ctrl status", bin(status))
93 if (status & (1<<DBGStat.STOPPED)) or (status & (1<<DBGStat.TERM)):
94 break
95
96 ####### JTAG to Wishbone ######
97
98 # write Wishbone address
99 yield from jtag_read_write_reg(dut, WB_ADDR, 64, 0)
100
101 # write/read wishbone data
102 for val in firmware:
103 data = yield from jtag_read_write_reg(dut, WB_WRRD, 64, val)
104 print ("wb write", hex(data))
105
106 # write Wishbone address
107 yield from jtag_read_write_reg(dut, WB_ADDR, 64, 0)
108
109 # confirm data written
110 for val in firmware:
111 data = yield from jtag_read_write_reg(dut, WB_READ, 64, 0)
112 print ("wb read", hex(data))
113
114 ####### JTAG to DMI Setup (IC-Reset, start) ######
115
116 # write DMI CTRL register - ICRESET
117 status = yield from writeread_dmi_addr(dut, DBGCore.CTRL,
118 1<<DBGCtrl.ICRESET)
119 print ("dmi ctrl status", hex(status))
120
121 # write DMI CTRL register - START
122 status = yield from writeread_dmi_addr(dut, DBGCore.CTRL,
123 1<<DBGCtrl.START)
124 print ("dmi ctrl status", hex(status))
125
126 # read STAT just for info
127 for i in range(4):
128 status = yield from read_dmi_addr(dut, DBGCore.STAT)
129 print ("dmi stat status", bin(status))
130
131 ####### done - tell dmi_sim to stop (otherwise it won't) ########
132
133 print ("jtag sim stopping")
134
135
136 if __name__ == '__main__':
137 # rather than the client access the JTAG bus directly
138 # create an alternative that the client sets
139 class Dummy: pass
140 cdut = Dummy()
141 cdut.cbus = JTAGInterface()
142
143 # set up client-server on port 44843-something
144 cdut.c = JTAGClient()
145
146 # take copy of ir_width and scan_len
147 cdut._ir_width = 4
148
149 flag = Signal()
150 m = Module()
151 m.d.sync += flag.eq(~flag) # get us a "sync" domain
152
153 sim = Simulator(m)
154 sim.add_clock(1e-6, domain="sync") # standard clock
155
156 data = [0x01, 0x02] # list of 64-bit words
157 sim.add_sync_process(wrap(jtag_sim(cdut, data)))
158
159 with sim.write_vcd("jtag_firmware_upload.vcd"):
160 sim.run()