7 from migen
.fhdl
.structure
import *
8 from litescope
.host
.reg
import *
9 from litescope
.host
.dump
import *
10 from litescope
.host
.truthtable
import *
12 def write_b(uart
, data
):
13 uart
.write(pack('B',data
))
15 class LiteScopeUART2WBDriver
:
18 def __init__(self
, port
, baudrate
=115200, addrmap
=None, busword
=8, debug
=False):
20 self
.baudrate
= str(baudrate
)
22 self
.uart
= serial
.Serial(port
, baudrate
, timeout
=0.25)
23 self
.regs
= build_map(addrmap
, busword
, self
.read
, self
.write
)
26 self
.uart
.flushOutput()
29 self
.uart
.flushInput()
31 self
.regs
.uart2wb_sel
.write(1)
37 self
.regs
.uart2wb_sel
.write(0)
40 self
.uart
.flushOutput()
43 def read(self
, addr
, burst_length
=1):
44 self
.uart
.flushInput()
45 write_b(self
.uart
, self
.READ_CMD
)
46 write_b(self
.uart
, burst_length
)
48 write_b(self
.uart
, (addr
& 0xff000000) >> 24)
49 write_b(self
.uart
, (addr
& 0x00ff0000) >> 16)
50 write_b(self
.uart
, (addr
& 0x0000ff00) >> 8)
51 write_b(self
.uart
, (addr
& 0x000000ff))
53 for i
in range(burst_length
):
57 val |
= ord(self
.uart
.read())
59 print("RD %08X @ %08X" %(val
, (addr
+i
)*4))
66 def write(self
, addr
, data
):
67 if isinstance(data
, list):
68 burst_length
= len(data
)
71 write_b(self
.uart
, self
.WRITE_CMD
)
72 write_b(self
.uart
, burst_length
)
74 write_b(self
.uart
, (addr
& 0xff000000) >> 24)
75 write_b(self
.uart
, (addr
& 0x00ff0000) >> 16)
76 write_b(self
.uart
, (addr
& 0x0000ff00) >> 8)
77 write_b(self
.uart
, (addr
& 0x000000ff))
78 if isinstance(data
, list):
79 for i
in range(len(data
)):
82 write_b(self
.uart
, (dat
& 0xff000000) >> 24)
85 print("WR %08X @ %08X" %(data
[i
], (addr
+ i
)*4))
89 write_b(self
.uart
, (dat
& 0xff000000) >> 24)
92 print("WR %08X @ %08X" %(data
, (addr
* 4)))
94 class LiteScopeIODriver():
95 def __init__(self
, regs
, name
):
101 for key
, value
in self
.regs
.d
.items():
103 key
= key
.replace(self
.name
+"_", "")
104 setattr(self
, key
, value
)
106 def write(self
, value
):
112 class LiteScopeLADriver():
113 def __init__(self
, regs
, name
, config_csv
=None, use_rle
=False):
116 self
.use_rle
= use_rle
117 if config_csv
is None:
118 self
.config_csv
= name
+ ".csv"
122 self
.dat
= Dat(self
.width
)
124 def get_config(self
):
125 csv_reader
= csv
.reader(open(self
.config_csv
), delimiter
=',', quotechar
='#')
126 for item
in csv_reader
:
129 setattr(self
, n
, int(v
))
131 def get_layout(self
):
133 csv_reader
= csv
.reader(open(self
.config_csv
), delimiter
=',', quotechar
='#')
134 for item
in csv_reader
:
137 self
.layout
.append((n
, int(v
)))
140 for key
, value
in self
.regs
.d
.items():
141 if self
.name
== key
[:len(self
.name
)]:
142 key
= key
.replace(self
.name
+ "_", "")
143 setattr(self
, key
, value
)
145 for name
, length
in self
.layout
:
146 setattr(self
, name
+ "_o", value
)
147 value
= value
*(2**length
)
149 for name
, length
in self
.layout
:
150 setattr(self
, name
+ "_m", (2**length
-1) << value
)
153 def show_state(self
, s
):
157 def prog_term(self
, port
, trigger
=0, mask
=0, cond
=None):
159 for k
, v
in cond
.items():
160 trigger |
= getattr(self
, k
+ "_o")*v
161 mask |
= getattr(self
, k
+ "_m")
162 t
= getattr(self
, "trigger_port{d}_trig".format(d
=int(port
)))
163 m
= getattr(self
, "trigger_port{d}_mask".format(d
=int(port
)))
167 def prog_range_detector(self
, port
, low
, high
):
168 l
= getattr(self
, "trigger_port{d}_low".format(d
=int(port
)))
169 h
= getattr(self
, "trigger_port{d}_high".format(d
=int(port
)))
173 def prog_edge_detector(self
, port
, rising_mask
, falling_mask
, both_mask
):
174 rm
= getattr(self
, "trigger_port{d}_rising_mask".format(d
=int(port
)))
175 fm
= getattr(self
, "trigger_port{d}_falling_mask".format(d
=int(port
)))
176 bm
= getattr(self
, "trigger_port{d}_both_mask".format(d
=int(port
)))
177 rm
.write(rising_mask
)
178 fm
.write(falling_mask
)
181 def prog_sum(self
, equation
):
182 datas
= gen_truth_table(equation
)
183 for adr
, dat
in enumerate(datas
):
184 self
.trigger_sum_prog_adr
.write(adr
)
185 self
.trigger_sum_prog_dat
.write(dat
)
186 self
.trigger_sum_prog_we
.write(1)
188 def config_rle(self
, v
):
189 self
.rle_enable
.write(v
)
192 return self
.recorder_done
.read()
195 self
.show_state("WAIT HIT")
196 while(not self
.is_done()):
199 def trigger(self
, offset
, length
):
200 self
.show_state("TRIG")
202 self
.config_rle(self
.use_rle
)
203 self
.recorder_offset
.write(offset
)
204 self
.recorder_length
.write(length
)
205 self
.recorder_trigger
.write(1)
208 self
.show_state("READ")
209 empty
= self
.recorder_read_empty
.read()
211 self
.dat
.append(self
.recorder_read_dat
.read())
212 empty
= self
.recorder_read_empty
.read()
213 self
.recorder_read_en
.write(1)
216 self
.dat
= self
.dat
.decode_rle()
219 def export(self
, export_fn
=None):
220 self
.show_state("EXPORT")
222 dump
.add_from_layout(self
.layout
, self
.dat
)
223 if ".vcd" in export_fn
:
224 VCDExport(dump
).write(export_fn
)
225 elif ".csv" in export_fn
:
226 CSVExport(dump
).write(export_fn
)
227 elif ".py" in export_fn
:
228 PYExport(dump
).write(export_fn
)
230 raise NotImplementedError