Merge branch 'master' of git.libre-soc.org:soc
[soc.git] / src / soc / simple / issuer.py
1 """simple core issuer
2
3 not in any way intended for production use. this runs a FSM that:
4
5 * reads the Program Counter from StateRegs
6 * reads an instruction from a fixed-size Test Memory
7 * issues it to the Simple Core
8 * waits for it to complete
9 * increments the PC
10 * does it all over again
11
12 the purpose of this module is to verify the functional correctness
13 of the Function Units in the absolute simplest and clearest possible
14 way, and to at provide something that can be further incrementally
15 improved.
16 """
17
18 from nmigen import (Elaboratable, Module, Signal, ClockSignal, ResetSignal,
19 ClockDomain, DomainRenamer, Mux, Const, Repl, Cat)
20 from nmigen.cli import rtlil
21 from nmigen.cli import main
22 import sys
23
24 from nmigen.lib.coding import PriorityEncoder
25
26 from soc.decoder.power_decoder import create_pdecode
27 from soc.decoder.power_decoder2 import PowerDecode2, SVP64PrefixDecoder
28 from soc.decoder.decode2execute1 import IssuerDecode2ToOperand
29 from soc.decoder.decode2execute1 import Data
30 from soc.experiment.testmem import TestMemory # test only for instructions
31 from soc.regfile.regfiles import StateRegs, FastRegs
32 from soc.simple.core import NonProductionCore
33 from soc.config.test.test_loadstore import TestMemPspec
34 from soc.config.ifetch import ConfigFetchUnit
35 from soc.decoder.power_enums import (MicrOp, SVP64PredInt, SVP64PredCR,
36 SVP64PredMode)
37 from soc.debug.dmi import CoreDebug, DMIInterface
38 from soc.debug.jtag import JTAG
39 from soc.config.pinouts import get_pinspecs
40 from soc.config.state import CoreState
41 from soc.interrupts.xics import XICS_ICP, XICS_ICS
42 from soc.bus.simple_gpio import SimpleGPIO
43 from soc.bus.SPBlock512W64B8W import SPBlock512W64B8W
44 from soc.clock.select import ClockSelect
45 from soc.clock.dummypll import DummyPLL
46 from soc.sv.svstate import SVSTATERec
47
48
49 from nmutil.util import rising_edge
50
51 def get_insn(f_instr_o, pc):
52 if f_instr_o.width == 32:
53 return f_instr_o
54 else:
55 # 64-bit: bit 2 of pc decides which word to select
56 return f_instr_o.word_select(pc[2], 32)
57
58 # gets state input or reads from state regfile
59 def state_get(m, state_i, name, regfile, regnum):
60 comb = m.d.comb
61 sync = m.d.sync
62 # read the PC
63 res = Signal(64, reset_less=True, name=name)
64 res_ok_delay = Signal(name="%s_ok_delay" % name)
65 sync += res_ok_delay.eq(~state_i.ok)
66 with m.If(state_i.ok):
67 # incoming override (start from pc_i)
68 comb += res.eq(state_i.data)
69 with m.Else():
70 # otherwise read StateRegs regfile for PC...
71 comb += regfile.ren.eq(1<<regnum)
72 # ... but on a 1-clock delay
73 with m.If(res_ok_delay):
74 comb += res.eq(regfile.data_o)
75 return res
76
77 def get_predint(m, mask, name):
78 """decode SVP64 predicate integer mask field to reg number and invert
79 this is identical to the equivalent function in ISACaller except that
80 it doesn't read the INT directly, it just decodes "what needs to be done"
81 i.e. which INT reg, whether it is shifted and whether it is bit-inverted.
82
83 * all1s is set to indicate that no mask is to be applied.
84 * regread indicates the GPR register number to be read
85 * invert is set to indicate that the register value is to be inverted
86 * unary indicates that the contents of the register is to be shifted 1<<r3
87 """
88 comb = m.d.comb
89 regread = Signal(5, name=name+"regread")
90 invert = Signal(name=name+"invert")
91 unary = Signal(name=name+"unary")
92 all1s = Signal(name=name+"all1s")
93 with m.Switch(mask):
94 with m.Case(SVP64PredInt.ALWAYS.value):
95 comb += all1s.eq(1) # use 0b1111 (all ones)
96 with m.Case(SVP64PredInt.R3_UNARY.value):
97 comb += regread.eq(3)
98 comb += unary.eq(1) # 1<<r3 - shift r3 (single bit)
99 with m.Case(SVP64PredInt.R3.value):
100 comb += regread.eq(3)
101 with m.Case(SVP64PredInt.R3_N.value):
102 comb += regread.eq(3)
103 comb += invert.eq(1)
104 with m.Case(SVP64PredInt.R10.value):
105 comb += regread.eq(10)
106 with m.Case(SVP64PredInt.R10_N.value):
107 comb += regread.eq(10)
108 comb += invert.eq(1)
109 with m.Case(SVP64PredInt.R30.value):
110 comb += regread.eq(30)
111 with m.Case(SVP64PredInt.R30_N.value):
112 comb += regread.eq(30)
113 comb += invert.eq(1)
114 return regread, invert, unary, all1s
115
116 def get_predcr(m, mask, name):
117 """decode SVP64 predicate CR to reg number field and invert status
118 this is identical to _get_predcr in ISACaller
119 """
120 comb = m.d.comb
121 idx = Signal(2, name=name+"idx")
122 invert = Signal(name=name+"crinvert")
123 with m.Switch(mask):
124 with m.Case(SVP64PredCR.LT.value):
125 comb += idx.eq(0)
126 comb += invert.eq(1)
127 with m.Case(SVP64PredCR.GE.value):
128 comb += idx.eq(0)
129 comb += invert.eq(0)
130 with m.Case(SVP64PredCR.GT.value):
131 comb += idx.eq(1)
132 comb += invert.eq(1)
133 with m.Case(SVP64PredCR.LE.value):
134 comb += idx.eq(1)
135 comb += invert.eq(0)
136 with m.Case(SVP64PredCR.EQ.value):
137 comb += idx.eq(2)
138 comb += invert.eq(1)
139 with m.Case(SVP64PredCR.NE.value):
140 comb += idx.eq(1)
141 comb += invert.eq(0)
142 with m.Case(SVP64PredCR.SO.value):
143 comb += idx.eq(3)
144 comb += invert.eq(1)
145 with m.Case(SVP64PredCR.NS.value):
146 comb += idx.eq(3)
147 comb += invert.eq(0)
148 return idx, invert
149
150
151 class TestIssuerInternal(Elaboratable):
152 """TestIssuer - reads instructions from TestMemory and issues them
153
154 efficiency and speed is not the main goal here: functional correctness
155 and code clarity is. optimisations (which almost 100% interfere with
156 easy understanding) come later.
157 """
158 def __init__(self, pspec):
159
160 # test is SVP64 is to be enabled
161 self.svp64_en = hasattr(pspec, "svp64") and (pspec.svp64 == True)
162
163 # and if regfiles are reduced
164 self.regreduce_en = (hasattr(pspec, "regreduce") and
165 (pspec.regreduce == True))
166
167 # JTAG interface. add this right at the start because if it's
168 # added it *modifies* the pspec, by adding enable/disable signals
169 # for parts of the rest of the core
170 self.jtag_en = hasattr(pspec, "debug") and pspec.debug == 'jtag'
171 if self.jtag_en:
172 subset = {'uart', 'mtwi', 'eint', 'gpio', 'mspi0', 'mspi1',
173 'pwm', 'sd0', 'sdr'}
174 self.jtag = JTAG(get_pinspecs(subset=subset))
175 # add signals to pspec to enable/disable icache and dcache
176 # (or data and intstruction wishbone if icache/dcache not included)
177 # https://bugs.libre-soc.org/show_bug.cgi?id=520
178 # TODO: do we actually care if these are not domain-synchronised?
179 # honestly probably not.
180 pspec.wb_icache_en = self.jtag.wb_icache_en
181 pspec.wb_dcache_en = self.jtag.wb_dcache_en
182 self.wb_sram_en = self.jtag.wb_sram_en
183 else:
184 self.wb_sram_en = Const(1)
185
186 # add 4k sram blocks?
187 self.sram4x4k = (hasattr(pspec, "sram4x4kblock") and
188 pspec.sram4x4kblock == True)
189 if self.sram4x4k:
190 self.sram4k = []
191 for i in range(4):
192 self.sram4k.append(SPBlock512W64B8W(name="sram4k_%d" % i,
193 features={'err'}))
194
195 # add interrupt controller?
196 self.xics = hasattr(pspec, "xics") and pspec.xics == True
197 if self.xics:
198 self.xics_icp = XICS_ICP()
199 self.xics_ics = XICS_ICS()
200 self.int_level_i = self.xics_ics.int_level_i
201
202 # add GPIO peripheral?
203 self.gpio = hasattr(pspec, "gpio") and pspec.gpio == True
204 if self.gpio:
205 self.simple_gpio = SimpleGPIO()
206 self.gpio_o = self.simple_gpio.gpio_o
207
208 # main instruction core. suitable for prototyping / demo only
209 self.core = core = NonProductionCore(pspec)
210
211 # instruction decoder. goes into Trap Record
212 pdecode = create_pdecode()
213 self.cur_state = CoreState("cur") # current state (MSR/PC/SVSTATE)
214 self.pdecode2 = PowerDecode2(pdecode, state=self.cur_state,
215 opkls=IssuerDecode2ToOperand,
216 svp64_en=self.svp64_en,
217 regreduce_en=self.regreduce_en)
218 if self.svp64_en:
219 self.svp64 = SVP64PrefixDecoder() # for decoding SVP64 prefix
220
221 # Test Instruction memory
222 self.imem = ConfigFetchUnit(pspec).fu
223
224 # DMI interface
225 self.dbg = CoreDebug()
226
227 # instruction go/monitor
228 self.pc_o = Signal(64, reset_less=True)
229 self.pc_i = Data(64, "pc_i") # set "ok" to indicate "please change me"
230 self.svstate_i = Data(32, "svstate_i") # ditto
231 self.core_bigendian_i = Signal() # TODO: set based on MSR.LE
232 self.busy_o = Signal(reset_less=True)
233 self.memerr_o = Signal(reset_less=True)
234
235 # STATE regfile read /write ports for PC, MSR, SVSTATE
236 staterf = self.core.regs.rf['state']
237 self.state_r_pc = staterf.r_ports['cia'] # PC rd
238 self.state_w_pc = staterf.w_ports['d_wr1'] # PC wr
239 self.state_r_msr = staterf.r_ports['msr'] # MSR rd
240 self.state_r_sv = staterf.r_ports['sv'] # SVSTATE rd
241 self.state_w_sv = staterf.w_ports['sv'] # SVSTATE wr
242
243 # DMI interface access
244 intrf = self.core.regs.rf['int']
245 crrf = self.core.regs.rf['cr']
246 xerrf = self.core.regs.rf['xer']
247 self.int_r = intrf.r_ports['dmi'] # INT read
248 self.cr_r = crrf.r_ports['full_cr_dbg'] # CR read
249 self.xer_r = xerrf.r_ports['full_xer'] # XER read
250
251 if self.svp64_en:
252 # for predication
253 self.int_pred = intrf.r_ports['pred'] # INT predicate read
254 self.cr_pred = crrf.r_ports['cr_pred'] # CR predicate read
255
256 # hack method of keeping an eye on whether branch/trap set the PC
257 self.state_nia = self.core.regs.rf['state'].w_ports['nia']
258 self.state_nia.wen.name = 'state_nia_wen'
259
260 # pulse to synchronize the simulator at instruction end
261 self.insn_done = Signal()
262
263 if self.svp64_en:
264 # store copies of predicate masks
265 self.srcmask = Signal(64)
266 self.dstmask = Signal(64)
267
268 def fetch_fsm(self, m, core, pc, svstate, nia, is_svp64_mode,
269 fetch_pc_ready_o, fetch_pc_valid_i,
270 fetch_insn_valid_o, fetch_insn_ready_i):
271 """fetch FSM
272
273 this FSM performs fetch of raw instruction data, partial-decodes
274 it 32-bit at a time to detect SVP64 prefixes, and will optionally
275 read a 2nd 32-bit quantity if that occurs.
276 """
277 comb = m.d.comb
278 sync = m.d.sync
279 pdecode2 = self.pdecode2
280 cur_state = self.cur_state
281 dec_opcode_i = pdecode2.dec.raw_opcode_in # raw opcode
282
283 msr_read = Signal(reset=1)
284
285 with m.FSM(name='fetch_fsm'):
286
287 # waiting (zzz)
288 with m.State("IDLE"):
289 comb += fetch_pc_ready_o.eq(1)
290 with m.If(fetch_pc_valid_i):
291 # instruction allowed to go: start by reading the PC
292 # capture the PC and also drop it into Insn Memory
293 # we have joined a pair of combinatorial memory
294 # lookups together. this is Generally Bad.
295 comb += self.imem.a_pc_i.eq(pc)
296 comb += self.imem.a_valid_i.eq(1)
297 comb += self.imem.f_valid_i.eq(1)
298 sync += cur_state.pc.eq(pc)
299 sync += cur_state.svstate.eq(svstate) # and svstate
300
301 # initiate read of MSR. arrives one clock later
302 comb += self.state_r_msr.ren.eq(1 << StateRegs.MSR)
303 sync += msr_read.eq(0)
304
305 m.next = "INSN_READ" # move to "wait for bus" phase
306
307 # dummy pause to find out why simulation is not keeping up
308 with m.State("INSN_READ"):
309 # one cycle later, msr/sv read arrives. valid only once.
310 with m.If(~msr_read):
311 sync += msr_read.eq(1) # yeah don't read it again
312 sync += cur_state.msr.eq(self.state_r_msr.data_o)
313 with m.If(self.imem.f_busy_o): # zzz...
314 # busy: stay in wait-read
315 comb += self.imem.a_valid_i.eq(1)
316 comb += self.imem.f_valid_i.eq(1)
317 with m.Else():
318 # not busy: instruction fetched
319 insn = get_insn(self.imem.f_instr_o, cur_state.pc)
320 if self.svp64_en:
321 svp64 = self.svp64
322 # decode the SVP64 prefix, if any
323 comb += svp64.raw_opcode_in.eq(insn)
324 comb += svp64.bigendian.eq(self.core_bigendian_i)
325 # pass the decoded prefix (if any) to PowerDecoder2
326 sync += pdecode2.sv_rm.eq(svp64.svp64_rm)
327 # remember whether this is a prefixed instruction, so
328 # the FSM can readily loop when VL==0
329 sync += is_svp64_mode.eq(svp64.is_svp64_mode)
330 # calculate the address of the following instruction
331 insn_size = Mux(svp64.is_svp64_mode, 8, 4)
332 sync += nia.eq(cur_state.pc + insn_size)
333 with m.If(~svp64.is_svp64_mode):
334 # with no prefix, store the instruction
335 # and hand it directly to the next FSM
336 sync += dec_opcode_i.eq(insn)
337 m.next = "INSN_READY"
338 with m.Else():
339 # fetch the rest of the instruction from memory
340 comb += self.imem.a_pc_i.eq(cur_state.pc + 4)
341 comb += self.imem.a_valid_i.eq(1)
342 comb += self.imem.f_valid_i.eq(1)
343 m.next = "INSN_READ2"
344 else:
345 # not SVP64 - 32-bit only
346 sync += nia.eq(cur_state.pc + 4)
347 sync += dec_opcode_i.eq(insn)
348 m.next = "INSN_READY"
349
350 with m.State("INSN_READ2"):
351 with m.If(self.imem.f_busy_o): # zzz...
352 # busy: stay in wait-read
353 comb += self.imem.a_valid_i.eq(1)
354 comb += self.imem.f_valid_i.eq(1)
355 with m.Else():
356 # not busy: instruction fetched
357 insn = get_insn(self.imem.f_instr_o, cur_state.pc+4)
358 sync += dec_opcode_i.eq(insn)
359 m.next = "INSN_READY"
360 # TODO: probably can start looking at pdecode2.rm_dec
361 # here or maybe even in INSN_READ state, if svp64_mode
362 # detected, in order to trigger - and wait for - the
363 # predicate reading.
364 if self.svp64_en:
365 pmode = pdecode2.rm_dec.predmode
366 """
367 if pmode != SVP64PredMode.ALWAYS.value:
368 fire predicate loading FSM and wait before
369 moving to INSN_READY
370 else:
371 sync += self.srcmask.eq(-1) # set to all 1s
372 sync += self.dstmask.eq(-1) # set to all 1s
373 m.next = "INSN_READY"
374 """
375
376 with m.State("INSN_READY"):
377 # hand over the instruction, to be decoded
378 comb += fetch_insn_valid_o.eq(1)
379 with m.If(fetch_insn_ready_i):
380 m.next = "IDLE"
381
382 def fetch_predicate_fsm(self, m,
383 pred_insn_valid_i, pred_insn_ready_o,
384 pred_mask_valid_o, pred_mask_ready_i):
385 """fetch_predicate_fsm - obtains (constructs in the case of CR)
386 src/dest predicate masks
387
388 https://bugs.libre-soc.org/show_bug.cgi?id=617
389 the predicates can be read here, by using IntRegs r_ports['pred']
390 or CRRegs r_ports['pred']. in the case of CRs it will have to
391 be done through multiple reads, extracting one relevant at a time.
392 later, a faster way would be to use the 32-bit-wide CR port but
393 this is more complex decoding, here. equivalent code used in
394 ISACaller is "from soc.decoder.isa.caller import get_predcr"
395
396 note: this ENTIRE FSM is not to be called when svp64 is disabled
397 """
398 comb = m.d.comb
399 sync = m.d.sync
400 pdecode2 = self.pdecode2
401 rm_dec = pdecode2.rm_dec # SVP64RMModeDecode
402 predmode = rm_dec.predmode
403 srcpred, dstpred = rm_dec.srcpred, rm_dec.dstpred
404 cr_pred, int_pred = self.cr_pred, self.int_pred # read regfiles
405
406 # elif predmode == CR:
407 # CR-src sidx, sinvert = get_predcr(m, srcpred)
408 # CR-dst didx, dinvert = get_predcr(m, dstpred)
409 # TODO read CR-src and CR-dst into self.srcmask+dstmask with loop
410 # has to cope with first one then the other
411 # for cr_idx = FSM-state-loop(0..VL-1):
412 # FSM-state-trigger-CR-read:
413 # cr_ren = (1<<7-(cr_idx+SVP64CROffs.CRPred))
414 # comb += cr_pred.ren.eq(cr_ren)
415 # FSM-state-1-clock-later-actual-Read:
416 # cr_field = Signal(4)
417 # cr_bit = Signal(1)
418 # # read the CR field, select the appropriate bit
419 # comb += cr_field.eq(cr_pred.data_o)
420 # comb += cr_bit.eq(cr_field.bit_select(idx)))
421 # # just like in branch BO tests
422 # comd += self.srcmask[cr_idx].eq(inv ^ cr_bit)
423
424 # decode predicates
425 sregread, sinvert, sunary, sall1s = get_predint(m, srcpred, 's')
426 dregread, dinvert, dunary, dall1s = get_predint(m, dstpred, 'd')
427 sidx, scrinvert = get_predcr(m, srcpred, 's')
428 didx, dcrinvert = get_predcr(m, dstpred, 'd')
429
430 with m.FSM(name="fetch_predicate"):
431
432 with m.State("FETCH_PRED_IDLE"):
433 comb += pred_insn_ready_o.eq(1)
434 with m.If(pred_insn_valid_i):
435 with m.If(predmode == SVP64PredMode.INT):
436 # skip fetching destination mask register, when zero
437 with m.If(dall1s):
438 sync += self.dstmask.eq(-1)
439 # directly go to fetch source mask register
440 # guaranteed not to be zero (otherwise predmode
441 # would be SVP64PredMode.ALWAYS, not INT)
442 comb += int_pred.addr.eq(sregread)
443 comb += int_pred.ren.eq(1)
444 m.next = "INT_SRC_READ"
445 # fetch destination predicate register
446 with m.Else():
447 comb += int_pred.addr.eq(dregread)
448 comb += int_pred.ren.eq(1)
449 m.next = "INT_DST_READ"
450 with m.Else():
451 sync += self.srcmask.eq(-1)
452 sync += self.dstmask.eq(-1)
453 m.next = "FETCH_PRED_DONE"
454
455 with m.State("INT_DST_READ"):
456 # store destination mask
457 inv = Repl(dinvert, 64)
458 sync += self.dstmask.eq(self.int_pred.data_o ^ inv)
459 # skip fetching source mask register, when zero
460 with m.If(sall1s):
461 sync += self.srcmask.eq(-1)
462 m.next = "FETCH_PRED_DONE"
463 # fetch source predicate register
464 with m.Else():
465 comb += int_pred.addr.eq(sregread)
466 comb += int_pred.ren.eq(1)
467 m.next = "INT_SRC_READ"
468
469 with m.State("INT_SRC_READ"):
470 # store source mask
471 inv = Repl(sinvert, 64)
472 sync += self.srcmask.eq(self.int_pred.data_o ^ inv)
473 m.next = "FETCH_PRED_DONE"
474
475 with m.State("FETCH_PRED_DONE"):
476 comb += pred_mask_valid_o.eq(1)
477 with m.If(pred_mask_ready_i):
478 m.next = "FETCH_PRED_IDLE"
479
480 def issue_fsm(self, m, core, pc_changed, sv_changed, nia,
481 dbg, core_rst, is_svp64_mode,
482 fetch_pc_ready_o, fetch_pc_valid_i,
483 fetch_insn_valid_o, fetch_insn_ready_i,
484 pred_insn_valid_i, pred_insn_ready_o,
485 pred_mask_valid_o, pred_mask_ready_i,
486 exec_insn_valid_i, exec_insn_ready_o,
487 exec_pc_valid_o, exec_pc_ready_i):
488 """issue FSM
489
490 decode / issue FSM. this interacts with the "fetch" FSM
491 through fetch_insn_ready/valid (incoming) and fetch_pc_ready/valid
492 (outgoing). also interacts with the "execute" FSM
493 through exec_insn_ready/valid (outgoing) and exec_pc_ready/valid
494 (incoming).
495 SVP64 RM prefixes have already been set up by the
496 "fetch" phase, so execute is fairly straightforward.
497 """
498
499 comb = m.d.comb
500 sync = m.d.sync
501 pdecode2 = self.pdecode2
502 cur_state = self.cur_state
503
504 # temporaries
505 dec_opcode_i = pdecode2.dec.raw_opcode_in # raw opcode
506
507 # for updating svstate (things like srcstep etc.)
508 update_svstate = Signal() # set this (below) if updating
509 new_svstate = SVSTATERec("new_svstate")
510 comb += new_svstate.eq(cur_state.svstate)
511
512 # precalculate srcstep+1 and dststep+1
513 cur_srcstep = cur_state.svstate.srcstep
514 cur_dststep = cur_state.svstate.dststep
515 next_srcstep = Signal.like(cur_srcstep)
516 next_dststep = Signal.like(cur_dststep)
517 comb += next_srcstep.eq(cur_state.svstate.srcstep+1)
518 comb += next_dststep.eq(cur_state.svstate.dststep+1)
519
520 with m.FSM(name="issue_fsm"):
521
522 # sync with the "fetch" phase which is reading the instruction
523 # at this point, there is no instruction running, that
524 # could inadvertently update the PC.
525 with m.State("ISSUE_START"):
526 # wait on "core stop" release, before next fetch
527 # need to do this here, in case we are in a VL==0 loop
528 with m.If(~dbg.core_stop_o & ~core_rst):
529 comb += fetch_pc_valid_i.eq(1) # tell fetch to start
530 with m.If(fetch_pc_ready_o): # fetch acknowledged us
531 m.next = "INSN_WAIT"
532 with m.Else():
533 # tell core it's stopped, and acknowledge debug handshake
534 comb += core.core_stopped_i.eq(1)
535 comb += dbg.core_stopped_i.eq(1)
536 # while stopped, allow updating the PC and SVSTATE
537 with m.If(self.pc_i.ok):
538 comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
539 comb += self.state_w_pc.data_i.eq(self.pc_i.data)
540 sync += pc_changed.eq(1)
541 with m.If(self.svstate_i.ok):
542 comb += new_svstate.eq(self.svstate_i.data)
543 comb += update_svstate.eq(1)
544 sync += sv_changed.eq(1)
545
546 # wait for an instruction to arrive from Fetch
547 with m.State("INSN_WAIT"):
548 comb += fetch_insn_ready_i.eq(1)
549 with m.If(fetch_insn_valid_o):
550 # loop into ISSUE_START if it's a SVP64 instruction
551 # and VL == 0. this because VL==0 is a for-loop
552 # from 0 to 0 i.e. always, always a NOP.
553 cur_vl = cur_state.svstate.vl
554 with m.If(is_svp64_mode & (cur_vl == 0)):
555 # update the PC before fetching the next instruction
556 # since we are in a VL==0 loop, no instruction was
557 # executed that we could be overwriting
558 comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
559 comb += self.state_w_pc.data_i.eq(nia)
560 comb += self.insn_done.eq(1)
561 m.next = "ISSUE_START"
562 with m.Else():
563 if self.svp64_en:
564 m.next = "PRED_START" # start fetching predicate
565 else:
566 m.next = "DECODE_SV" # skip predication
567
568 with m.State("PRED_START"):
569 comb += pred_insn_valid_i.eq(1) # tell fetch_pred to start
570 with m.If(pred_insn_ready_o): # fetch_pred acknowledged us
571 m.next = "MASK_WAIT"
572
573 with m.State("MASK_WAIT"):
574 comb += pred_mask_ready_i.eq(1) # ready to receive the masks
575 with m.If(pred_mask_valid_o): # predication masks are ready
576 m.next = "PRED_SKIP"
577
578 # skip zeros in predicate
579 with m.State("PRED_SKIP"):
580 with m.If(~is_svp64_mode):
581 m.next = "DECODE_SV" # nothing to do
582 with m.Else():
583 if self.svp64_en:
584 pred_src_zero = pdecode2.rm_dec.pred_sz
585 pred_dst_zero = pdecode2.rm_dec.pred_dz
586
587 # new srcstep, after skipping zeros
588 skip_srcstep = Signal.like(cur_srcstep)
589 # value to be added to the current srcstep
590 src_delta = Signal.like(cur_srcstep)
591 # add leading zeros to srcstep, if not in zero mode
592 with m.If(~pred_src_zero):
593 # priority encoder (count leading zeros)
594 # append guard bit, in case the mask is all zeros
595 pri_enc_src = PriorityEncoder(65)
596 m.submodules.pri_enc_src = pri_enc_src
597 comb += pri_enc_src.i.eq(Cat(self.srcmask, 1))
598 comb += src_delta.eq(pri_enc_src.o)
599 # apply delta to srcstep
600 comb += skip_srcstep.eq(cur_srcstep + src_delta)
601 # shift-out all leading zeros from the mask
602 # plus the leading "one" bit
603 sync += self.srcmask.eq(self.srcmask >> (src_delta+1))
604
605 # same as above, but for dststep
606 skip_dststep = Signal.like(cur_dststep)
607 dst_delta = Signal.like(cur_dststep)
608 with m.If(~pred_dst_zero):
609 pri_enc_dst = PriorityEncoder(65)
610 m.submodules.pri_enc_dst = pri_enc_dst
611 comb += pri_enc_dst.i.eq(Cat(self.dstmask, 1))
612 comb += dst_delta.eq(pri_enc_dst.o)
613 comb += skip_dststep.eq(cur_dststep + dst_delta)
614 sync += self.dstmask.eq(self.dstmask >> (dst_delta+1))
615
616 # TODO: initialize mask[VL]=1 to avoid passing past VL
617 with m.If((skip_srcstep >= cur_vl) |
618 (skip_dststep >= cur_vl)):
619 # end of VL loop. Update PC and reset src/dst step
620 comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
621 comb += self.state_w_pc.data_i.eq(nia)
622 comb += new_svstate.srcstep.eq(0)
623 comb += new_svstate.dststep.eq(0)
624 comb += update_svstate.eq(1)
625 # go back to Issue
626 m.next = "ISSUE_START"
627 with m.Else():
628 # update new src/dst step
629 comb += new_svstate.srcstep.eq(skip_srcstep)
630 comb += new_svstate.dststep.eq(skip_dststep)
631 comb += update_svstate.eq(1)
632 # proceed to Decode
633 m.next = "DECODE_SV"
634
635 # after src/dst step have been updated, we are ready
636 # to decode the instruction
637 with m.State("DECODE_SV"):
638 # decode the instruction
639 sync += core.e.eq(pdecode2.e)
640 sync += core.state.eq(cur_state)
641 sync += core.raw_insn_i.eq(dec_opcode_i)
642 sync += core.bigendian_i.eq(self.core_bigendian_i)
643 # set RA_OR_ZERO detection in satellite decoders
644 sync += core.sv_a_nz.eq(pdecode2.sv_a_nz)
645 m.next = "INSN_EXECUTE" # move to "execute"
646
647 # handshake with execution FSM, move to "wait" once acknowledged
648 with m.State("INSN_EXECUTE"):
649 comb += exec_insn_valid_i.eq(1) # trigger execute
650 with m.If(exec_insn_ready_o): # execute acknowledged us
651 m.next = "EXECUTE_WAIT"
652
653 with m.State("EXECUTE_WAIT"):
654 # wait on "core stop" release, at instruction end
655 # need to do this here, in case we are in a VL>1 loop
656 with m.If(~dbg.core_stop_o & ~core_rst):
657 comb += exec_pc_ready_i.eq(1)
658 with m.If(exec_pc_valid_o):
659
660 # was this the last loop iteration?
661 is_last = Signal()
662 cur_vl = cur_state.svstate.vl
663 comb += is_last.eq(next_srcstep == cur_vl)
664
665 # if either PC or SVSTATE were changed by the previous
666 # instruction, go directly back to Fetch, without
667 # updating either PC or SVSTATE
668 with m.If(pc_changed | sv_changed):
669 m.next = "ISSUE_START"
670
671 # also return to Fetch, when no output was a vector
672 # (regardless of SRCSTEP and VL), or when the last
673 # instruction was really the last one of the VL loop
674 with m.Elif((~pdecode2.loop_continue) | is_last):
675 # before going back to fetch, update the PC state
676 # register with the NIA.
677 # ok here we are not reading the branch unit.
678 # TODO: this just blithely overwrites whatever
679 # pipeline updated the PC
680 comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
681 comb += self.state_w_pc.data_i.eq(nia)
682 # reset SRCSTEP before returning to Fetch
683 with m.If(pdecode2.loop_continue):
684 comb += new_svstate.srcstep.eq(0)
685 comb += new_svstate.dststep.eq(0)
686 comb += update_svstate.eq(1)
687 m.next = "ISSUE_START"
688
689 # returning to Execute? then, first update SRCSTEP
690 with m.Else():
691 comb += new_svstate.srcstep.eq(next_srcstep)
692 comb += new_svstate.dststep.eq(next_dststep)
693 comb += update_svstate.eq(1)
694 # return to mask skip loop
695 m.next = "PRED_SKIP"
696
697 with m.Else():
698 comb += core.core_stopped_i.eq(1)
699 comb += dbg.core_stopped_i.eq(1)
700 # while stopped, allow updating the PC and SVSTATE
701 with m.If(self.pc_i.ok):
702 comb += self.state_w_pc.wen.eq(1 << StateRegs.PC)
703 comb += self.state_w_pc.data_i.eq(self.pc_i.data)
704 sync += pc_changed.eq(1)
705 with m.If(self.svstate_i.ok):
706 comb += new_svstate.eq(self.svstate_i.data)
707 comb += update_svstate.eq(1)
708 sync += sv_changed.eq(1)
709
710 # check if svstate needs updating: if so, write it to State Regfile
711 with m.If(update_svstate):
712 comb += self.state_w_sv.wen.eq(1<<StateRegs.SVSTATE)
713 comb += self.state_w_sv.data_i.eq(new_svstate)
714 sync += cur_state.svstate.eq(new_svstate) # for next clock
715
716 def execute_fsm(self, m, core, pc_changed, sv_changed,
717 exec_insn_valid_i, exec_insn_ready_o,
718 exec_pc_valid_o, exec_pc_ready_i):
719 """execute FSM
720
721 execute FSM. this interacts with the "issue" FSM
722 through exec_insn_ready/valid (incoming) and exec_pc_ready/valid
723 (outgoing). SVP64 RM prefixes have already been set up by the
724 "issue" phase, so execute is fairly straightforward.
725 """
726
727 comb = m.d.comb
728 sync = m.d.sync
729 pdecode2 = self.pdecode2
730
731 # temporaries
732 core_busy_o = core.busy_o # core is busy
733 core_ivalid_i = core.ivalid_i # instruction is valid
734 core_issue_i = core.issue_i # instruction is issued
735 insn_type = core.e.do.insn_type # instruction MicroOp type
736
737 with m.FSM(name="exec_fsm"):
738
739 # waiting for instruction bus (stays there until not busy)
740 with m.State("INSN_START"):
741 comb += exec_insn_ready_o.eq(1)
742 with m.If(exec_insn_valid_i):
743 comb += core_ivalid_i.eq(1) # instruction is valid
744 comb += core_issue_i.eq(1) # and issued
745 sync += sv_changed.eq(0)
746 sync += pc_changed.eq(0)
747 m.next = "INSN_ACTIVE" # move to "wait completion"
748
749 # instruction started: must wait till it finishes
750 with m.State("INSN_ACTIVE"):
751 with m.If(insn_type != MicrOp.OP_NOP):
752 comb += core_ivalid_i.eq(1) # instruction is valid
753 # note changes to PC and SVSTATE
754 with m.If(self.state_nia.wen & (1<<StateRegs.SVSTATE)):
755 sync += sv_changed.eq(1)
756 with m.If(self.state_nia.wen & (1<<StateRegs.PC)):
757 sync += pc_changed.eq(1)
758 with m.If(~core_busy_o): # instruction done!
759 comb += exec_pc_valid_o.eq(1)
760 with m.If(exec_pc_ready_i):
761 comb += self.insn_done.eq(1)
762 m.next = "INSN_START" # back to fetch
763
764 def setup_peripherals(self, m):
765 comb, sync = m.d.comb, m.d.sync
766
767 m.submodules.core = core = DomainRenamer("coresync")(self.core)
768 m.submodules.imem = imem = self.imem
769 m.submodules.dbg = dbg = self.dbg
770 if self.jtag_en:
771 m.submodules.jtag = jtag = self.jtag
772 # TODO: UART2GDB mux, here, from external pin
773 # see https://bugs.libre-soc.org/show_bug.cgi?id=499
774 sync += dbg.dmi.connect_to(jtag.dmi)
775
776 cur_state = self.cur_state
777
778 # 4x 4k SRAM blocks. these simply "exist", they get routed in litex
779 if self.sram4x4k:
780 for i, sram in enumerate(self.sram4k):
781 m.submodules["sram4k_%d" % i] = sram
782 comb += sram.enable.eq(self.wb_sram_en)
783
784 # XICS interrupt handler
785 if self.xics:
786 m.submodules.xics_icp = icp = self.xics_icp
787 m.submodules.xics_ics = ics = self.xics_ics
788 comb += icp.ics_i.eq(ics.icp_o) # connect ICS to ICP
789 sync += cur_state.eint.eq(icp.core_irq_o) # connect ICP to core
790
791 # GPIO test peripheral
792 if self.gpio:
793 m.submodules.simple_gpio = simple_gpio = self.simple_gpio
794
795 # connect one GPIO output to ICS bit 15 (like in microwatt soc.vhdl)
796 # XXX causes litex ECP5 test to get wrong idea about input and output
797 # (but works with verilator sim *sigh*)
798 #if self.gpio and self.xics:
799 # comb += self.int_level_i[15].eq(simple_gpio.gpio_o[0])
800
801 # instruction decoder
802 pdecode = create_pdecode()
803 m.submodules.dec2 = pdecode2 = self.pdecode2
804 if self.svp64_en:
805 m.submodules.svp64 = svp64 = self.svp64
806
807 # convenience
808 dmi, d_reg, d_cr, d_xer, = dbg.dmi, dbg.d_gpr, dbg.d_cr, dbg.d_xer
809 intrf = self.core.regs.rf['int']
810
811 # clock delay power-on reset
812 cd_por = ClockDomain(reset_less=True)
813 cd_sync = ClockDomain()
814 core_sync = ClockDomain("coresync")
815 m.domains += cd_por, cd_sync, core_sync
816
817 ti_rst = Signal(reset_less=True)
818 delay = Signal(range(4), reset=3)
819 with m.If(delay != 0):
820 m.d.por += delay.eq(delay - 1)
821 comb += cd_por.clk.eq(ClockSignal())
822
823 # power-on reset delay
824 core_rst = ResetSignal("coresync")
825 comb += ti_rst.eq(delay != 0 | dbg.core_rst_o | ResetSignal())
826 comb += core_rst.eq(ti_rst)
827
828 # busy/halted signals from core
829 comb += self.busy_o.eq(core.busy_o)
830 comb += pdecode2.dec.bigendian.eq(self.core_bigendian_i)
831
832 # temporary hack: says "go" immediately for both address gen and ST
833 l0 = core.l0
834 ldst = core.fus.fus['ldst0']
835 st_go_edge = rising_edge(m, ldst.st.rel_o)
836 m.d.comb += ldst.ad.go_i.eq(ldst.ad.rel_o) # link addr-go direct to rel
837 m.d.comb += ldst.st.go_i.eq(st_go_edge) # link store-go to rising rel
838
839 return core_rst
840
841 def elaborate(self, platform):
842 m = Module()
843 # convenience
844 comb, sync = m.d.comb, m.d.sync
845 cur_state = self.cur_state
846 pdecode2 = self.pdecode2
847 dbg = self.dbg
848 core = self.core
849
850 # set up peripherals and core
851 core_rst = self.setup_peripherals(m)
852
853 # PC and instruction from I-Memory
854 comb += self.pc_o.eq(cur_state.pc)
855 pc_changed = Signal() # note write to PC
856 sv_changed = Signal() # note write to SVSTATE
857
858 # read state either from incoming override or from regfile
859 # TODO: really should be doing MSR in the same way
860 pc = state_get(m, self.pc_i, "pc", # read PC
861 self.state_r_pc, StateRegs.PC)
862 svstate = state_get(m, self.svstate_i, "svstate", # read SVSTATE
863 self.state_r_sv, StateRegs.SVSTATE)
864
865 # don't write pc every cycle
866 comb += self.state_w_pc.wen.eq(0)
867 comb += self.state_w_pc.data_i.eq(0)
868
869 # don't read msr every cycle
870 comb += self.state_r_msr.ren.eq(0)
871
872 # address of the next instruction, in the absence of a branch
873 # depends on the instruction size
874 nia = Signal(64, reset_less=True)
875
876 # connect up debug signals
877 # TODO comb += core.icache_rst_i.eq(dbg.icache_rst_o)
878 comb += dbg.terminate_i.eq(core.core_terminate_o)
879 comb += dbg.state.pc.eq(pc)
880 comb += dbg.state.svstate.eq(svstate)
881 comb += dbg.state.msr.eq(cur_state.msr)
882
883 # pass the prefix mode from Fetch to Issue, so the latter can loop
884 # on VL==0
885 is_svp64_mode = Signal()
886
887 # there are *THREE* FSMs, fetch (32/64-bit) issue, decode/execute.
888 # these are the handshake signals between fetch and decode/execute
889
890 # fetch FSM can run as soon as the PC is valid
891 fetch_pc_valid_i = Signal() # Execute tells Fetch "start next read"
892 fetch_pc_ready_o = Signal() # Fetch Tells SVSTATE "proceed"
893
894 # fetch FSM hands over the instruction to be decoded / issued
895 fetch_insn_valid_o = Signal()
896 fetch_insn_ready_i = Signal()
897
898 # predicate fetch FSM decodes and fetches the predicate
899 pred_insn_valid_i = Signal()
900 pred_insn_ready_o = Signal()
901
902 # predicate fetch FSM delivers the masks
903 pred_mask_valid_o = Signal()
904 pred_mask_ready_i = Signal()
905
906 # issue FSM delivers the instruction to the be executed
907 exec_insn_valid_i = Signal()
908 exec_insn_ready_o = Signal()
909
910 # execute FSM, hands over the PC/SVSTATE back to the issue FSM
911 exec_pc_valid_o = Signal()
912 exec_pc_ready_i = Signal()
913
914 # the FSMs here are perhaps unusual in that they detect conditions
915 # then "hold" information, combinatorially, for the core
916 # (as opposed to using sync - which would be on a clock's delay)
917 # this includes the actual opcode, valid flags and so on.
918
919 # Fetch, then predicate fetch, then Issue, then Execute.
920 # Issue is where the VL for-loop # lives. the ready/valid
921 # signalling is used to communicate between the four.
922
923 self.fetch_fsm(m, core, pc, svstate, nia, is_svp64_mode,
924 fetch_pc_ready_o, fetch_pc_valid_i,
925 fetch_insn_valid_o, fetch_insn_ready_i)
926
927 self.issue_fsm(m, core, pc_changed, sv_changed, nia,
928 dbg, core_rst, is_svp64_mode,
929 fetch_pc_ready_o, fetch_pc_valid_i,
930 fetch_insn_valid_o, fetch_insn_ready_i,
931 pred_insn_valid_i, pred_insn_ready_o,
932 pred_mask_valid_o, pred_mask_ready_i,
933 exec_insn_valid_i, exec_insn_ready_o,
934 exec_pc_valid_o, exec_pc_ready_i)
935
936 if self.svp64_en:
937 self.fetch_predicate_fsm(m,
938 pred_insn_valid_i, pred_insn_ready_o,
939 pred_mask_valid_o, pred_mask_ready_i)
940
941 self.execute_fsm(m, core, pc_changed, sv_changed,
942 exec_insn_valid_i, exec_insn_ready_o,
943 exec_pc_valid_o, exec_pc_ready_i)
944
945 # this bit doesn't have to be in the FSM: connect up to read
946 # regfiles on demand from DMI
947 self.do_dmi(m, dbg)
948
949 # DEC and TB inc/dec FSM. copy of DEC is put into CoreState,
950 # (which uses that in PowerDecoder2 to raise 0x900 exception)
951 self.tb_dec_fsm(m, cur_state.dec)
952
953 return m
954
955 def do_dmi(self, m, dbg):
956 """deals with DMI debug requests
957
958 currently only provides read requests for the INT regfile, CR and XER
959 it will later also deal with *writing* to these regfiles.
960 """
961 comb = m.d.comb
962 sync = m.d.sync
963 dmi, d_reg, d_cr, d_xer, = dbg.dmi, dbg.d_gpr, dbg.d_cr, dbg.d_xer
964 intrf = self.core.regs.rf['int']
965
966 with m.If(d_reg.req): # request for regfile access being made
967 # TODO: error-check this
968 # XXX should this be combinatorial? sync better?
969 if intrf.unary:
970 comb += self.int_r.ren.eq(1<<d_reg.addr)
971 else:
972 comb += self.int_r.addr.eq(d_reg.addr)
973 comb += self.int_r.ren.eq(1)
974 d_reg_delay = Signal()
975 sync += d_reg_delay.eq(d_reg.req)
976 with m.If(d_reg_delay):
977 # data arrives one clock later
978 comb += d_reg.data.eq(self.int_r.data_o)
979 comb += d_reg.ack.eq(1)
980
981 # sigh same thing for CR debug
982 with m.If(d_cr.req): # request for regfile access being made
983 comb += self.cr_r.ren.eq(0b11111111) # enable all
984 d_cr_delay = Signal()
985 sync += d_cr_delay.eq(d_cr.req)
986 with m.If(d_cr_delay):
987 # data arrives one clock later
988 comb += d_cr.data.eq(self.cr_r.data_o)
989 comb += d_cr.ack.eq(1)
990
991 # aaand XER...
992 with m.If(d_xer.req): # request for regfile access being made
993 comb += self.xer_r.ren.eq(0b111111) # enable all
994 d_xer_delay = Signal()
995 sync += d_xer_delay.eq(d_xer.req)
996 with m.If(d_xer_delay):
997 # data arrives one clock later
998 comb += d_xer.data.eq(self.xer_r.data_o)
999 comb += d_xer.ack.eq(1)
1000
1001 def tb_dec_fsm(self, m, spr_dec):
1002 """tb_dec_fsm
1003
1004 this is a FSM for updating either dec or tb. it runs alternately
1005 DEC, TB, DEC, TB. note that SPR pipeline could have written a new
1006 value to DEC, however the regfile has "passthrough" on it so this
1007 *should* be ok.
1008
1009 see v3.0B p1097-1099 for Timeer Resource and p1065 and p1076
1010 """
1011
1012 comb, sync = m.d.comb, m.d.sync
1013 fast_rf = self.core.regs.rf['fast']
1014 fast_r_dectb = fast_rf.r_ports['issue'] # DEC/TB
1015 fast_w_dectb = fast_rf.w_ports['issue'] # DEC/TB
1016
1017 with m.FSM() as fsm:
1018
1019 # initiates read of current DEC
1020 with m.State("DEC_READ"):
1021 comb += fast_r_dectb.addr.eq(FastRegs.DEC)
1022 comb += fast_r_dectb.ren.eq(1)
1023 m.next = "DEC_WRITE"
1024
1025 # waits for DEC read to arrive (1 cycle), updates with new value
1026 with m.State("DEC_WRITE"):
1027 new_dec = Signal(64)
1028 # TODO: MSR.LPCR 32-bit decrement mode
1029 comb += new_dec.eq(fast_r_dectb.data_o - 1)
1030 comb += fast_w_dectb.addr.eq(FastRegs.DEC)
1031 comb += fast_w_dectb.wen.eq(1)
1032 comb += fast_w_dectb.data_i.eq(new_dec)
1033 sync += spr_dec.eq(new_dec) # copy into cur_state for decoder
1034 m.next = "TB_READ"
1035
1036 # initiates read of current TB
1037 with m.State("TB_READ"):
1038 comb += fast_r_dectb.addr.eq(FastRegs.TB)
1039 comb += fast_r_dectb.ren.eq(1)
1040 m.next = "TB_WRITE"
1041
1042 # waits for read TB to arrive, initiates write of current TB
1043 with m.State("TB_WRITE"):
1044 new_tb = Signal(64)
1045 comb += new_tb.eq(fast_r_dectb.data_o + 1)
1046 comb += fast_w_dectb.addr.eq(FastRegs.TB)
1047 comb += fast_w_dectb.wen.eq(1)
1048 comb += fast_w_dectb.data_i.eq(new_tb)
1049 m.next = "DEC_READ"
1050
1051 return m
1052
1053 def __iter__(self):
1054 yield from self.pc_i.ports()
1055 yield self.pc_o
1056 yield self.memerr_o
1057 yield from self.core.ports()
1058 yield from self.imem.ports()
1059 yield self.core_bigendian_i
1060 yield self.busy_o
1061
1062 def ports(self):
1063 return list(self)
1064
1065 def external_ports(self):
1066 ports = self.pc_i.ports()
1067 ports += [self.pc_o, self.memerr_o, self.core_bigendian_i, self.busy_o,
1068 ]
1069
1070 if self.jtag_en:
1071 ports += list(self.jtag.external_ports())
1072 else:
1073 # don't add DMI if JTAG is enabled
1074 ports += list(self.dbg.dmi.ports())
1075
1076 ports += list(self.imem.ibus.fields.values())
1077 ports += list(self.core.l0.cmpi.lsmem.lsi.slavebus.fields.values())
1078
1079 if self.sram4x4k:
1080 for sram in self.sram4k:
1081 ports += list(sram.bus.fields.values())
1082
1083 if self.xics:
1084 ports += list(self.xics_icp.bus.fields.values())
1085 ports += list(self.xics_ics.bus.fields.values())
1086 ports.append(self.int_level_i)
1087
1088 if self.gpio:
1089 ports += list(self.simple_gpio.bus.fields.values())
1090 ports.append(self.gpio_o)
1091
1092 return ports
1093
1094 def ports(self):
1095 return list(self)
1096
1097
1098 class TestIssuer(Elaboratable):
1099 def __init__(self, pspec):
1100 self.ti = TestIssuerInternal(pspec)
1101
1102 self.pll = DummyPLL()
1103
1104 # PLL direct clock or not
1105 self.pll_en = hasattr(pspec, "use_pll") and pspec.use_pll
1106 if self.pll_en:
1107 self.pll_18_o = Signal(reset_less=True)
1108
1109 def elaborate(self, platform):
1110 m = Module()
1111 comb = m.d.comb
1112
1113 # TestIssuer runs at direct clock
1114 m.submodules.ti = ti = self.ti
1115 cd_int = ClockDomain("coresync")
1116
1117 if self.pll_en:
1118 # ClockSelect runs at PLL output internal clock rate
1119 m.submodules.pll = pll = self.pll
1120
1121 # add clock domains from PLL
1122 cd_pll = ClockDomain("pllclk")
1123 m.domains += cd_pll
1124
1125 # PLL clock established. has the side-effect of running clklsel
1126 # at the PLL's speed (see DomainRenamer("pllclk") above)
1127 pllclk = ClockSignal("pllclk")
1128 comb += pllclk.eq(pll.clk_pll_o)
1129
1130 # wire up external 24mhz to PLL
1131 comb += pll.clk_24_i.eq(ClockSignal())
1132
1133 # output 18 mhz PLL test signal
1134 comb += self.pll_18_o.eq(pll.pll_18_o)
1135
1136 # now wire up ResetSignals. don't mind them being in this domain
1137 pll_rst = ResetSignal("pllclk")
1138 comb += pll_rst.eq(ResetSignal())
1139
1140 # internal clock is set to selector clock-out. has the side-effect of
1141 # running TestIssuer at this speed (see DomainRenamer("intclk") above)
1142 intclk = ClockSignal("coresync")
1143 if self.pll_en:
1144 comb += intclk.eq(pll.clk_pll_o)
1145 else:
1146 comb += intclk.eq(ClockSignal())
1147
1148 return m
1149
1150 def ports(self):
1151 return list(self.ti.ports()) + list(self.pll.ports()) + \
1152 [ClockSignal(), ResetSignal()]
1153
1154 def external_ports(self):
1155 ports = self.ti.external_ports()
1156 ports.append(ClockSignal())
1157 ports.append(ResetSignal())
1158 if self.pll_en:
1159 ports.append(self.pll.clk_sel_i)
1160 ports.append(self.pll_18_o)
1161 ports.append(self.pll.pll_lck_o)
1162 return ports
1163
1164
1165 if __name__ == '__main__':
1166 units = {'alu': 1, 'cr': 1, 'branch': 1, 'trap': 1, 'logical': 1,
1167 'spr': 1,
1168 'div': 1,
1169 'mul': 1,
1170 'shiftrot': 1
1171 }
1172 pspec = TestMemPspec(ldst_ifacetype='bare_wb',
1173 imem_ifacetype='bare_wb',
1174 addr_wid=48,
1175 mask_wid=8,
1176 reg_wid=64,
1177 units=units)
1178 dut = TestIssuer(pspec)
1179 vl = main(dut, ports=dut.ports(), name="test_issuer")
1180
1181 if len(sys.argv) == 1:
1182 vl = rtlil.convert(dut, ports=dut.external_ports(), name="test_issuer")
1183 with open("test_issuer.il", "w") as f:
1184 f.write(vl)