fbae0086b67304c0b339463b98f8362d8b8a54d1
[soc.git] / src / soc / scoreboard / test_mem_fu_matrix.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Module, Const, Signal, Array, Cat, Elaboratable
4
5 from regfile.regfile import RegFileArray, treereduce
6 from soc.scoreboard.ldst_matrix import LDSTDepMatrix
7 from soc.scoreboard.fu_mem_matrix import FUMemDepMatrix
8 from soc.scoreboard.global_pending import GlobalPending
9 from soc.scoreboard.group_picker import GroupPicker
10 from soc.scoreboard.issue_unit import IssueUnitGroup, IssueUnitArray, RegDecode
11 from soc.scoreboard.shadow import ShadowMatrix, BranchSpeculationRecord
12
13 from nmutil.latch import SRLatch
14 from nmutil.nmoperator import eq
15
16 from random import randint, seed
17 from copy import deepcopy
18 from math import log
19
20
21 class Memory(Elaboratable):
22 def __init__(self, regwid, addrw):
23 self.ddepth = regwid/8
24 depth = (1<<addrw) / self.ddepth
25 self.adr = Signal(addrw)
26 self.dat_r = Signal(regwid)
27 self.dat_w = Signal(regwid)
28 self.we = Signal()
29 self.mem = Memory(width=regwid, depth=depth, init=range(0, depth))
30
31 def elaborate(self, platform):
32 m = Module()
33 m.submodules.rdport = rdport = self.mem.read_port()
34 m.submodules.wrport = wrport = self.mem.write_port()
35 m.d.comb += [
36 rdport.addr.eq(self.adr[self.ddepth:]), # ignore low bits
37 self.dat_r.eq(rdport.data),
38 wrport.addr.eq(self.adr),
39 wrport.data.eq(self.dat_w),
40 wrport.en.eq(self.we),
41 ]
42 return m
43
44
45 class MemSim:
46 def __init__(self, regwid, addrw):
47 self.regwid = regwid
48 self.ddepth = regwid//8
49 depth = (1<<addrw) // self.ddepth
50 self.mem = list(range(0, depth))
51
52 def ld(self, addr):
53 return self.mem[addr>>self.ddepth]
54
55 def st(self, addr, data):
56 self.mem[addr>>self.ddepth] = data & ((1<<self.regwid)-1)
57
58
59 class MemFunctionUnits(Elaboratable):
60
61 def __init__(self, n_int_alus):
62 self.n_int_alus = n_int_alus
63
64 self.ld_i = Signal(n_int_alus, reset_less=True) # Dest R# in
65 self.st_i = Signal(n_int_alus, reset_less=True) # oper1 R# in
66
67 self.load_hit_i = Signal(n_int_alus, reset_less=True) # Load Hit
68 self.stwd_hit_i = Signal(n_int_alus, reset_less=True) # Store Hit
69
70 #self.g_int_st_pend_o = Signal(n_int_alus, reset_less=True)
71 #self.g_int_ld_pend_o = Signal(n_int_alus, reset_less=True)
72
73 #self.ld_rsel_o = Signal(n_int_alus, reset_less=True) # dest reg (bot)
74 #self.st_rsel_o = Signal(n_int_alus, reset_less=True) # src1 reg (bot)
75
76 self.req_rel_i = Signal(n_int_alus, reset_less = True)
77 self.loadable_o = Signal(n_int_alus, reset_less=True)
78 self.storable_o = Signal(n_int_alus, reset_less=True)
79
80 self.go_st_i = Signal(n_int_alus, reset_less=True)
81 self.go_ld_i = Signal(n_int_alus, reset_less=True)
82 self.go_die_i = Signal(n_int_alus, reset_less=True)
83 self.req_rel_o = Signal(n_int_alus, reset_less=True)
84 self.fn_issue_i = Signal(n_int_alus, reset_less=True)
85
86 # Note: FURegs ld_pend_o is also outputted from here, for use in WaWGrid
87
88 def elaborate(self, platform):
89 m = Module()
90 comb = m.d.comb
91 sync = m.d.sync
92
93 n_intfus = self.n_int_alus
94
95 # Integer LD/ST Dep Matrix
96 ldstdeps = LDSTDepMatrix(n_intfus)
97 m.submodules.ldstdeps = ldstdeps
98 # Integer FU-Mem Dep Matrix
99 fumemdeps = FUMemDepMatrix(n_intfus, n_intfus)
100 m.submodules.fumemdeps = fumemdeps
101
102 #comb += self.g_int_st_pend_o.eq(fumemdeps.v_st_rsel_o)
103 #comb += self.g_int_ld_pend_o.eq(fumemdeps.v_ld_rsel_o)
104
105 #comb += fumemdeps.st_pend_i.eq(fumemdeps.v_st_rsel_o)
106 #comb += fumemdeps.ld_pend_i.eq(fumemdeps.v_ld_rsel_o)
107
108 #comb += ldstdeps.st_pend_i.eq(fumemdeps.st_pend_o)
109 #comb += ldstdeps.ld_pend_i.eq(fumemdeps.ld_pend_o)
110 #self.ld_pend_o = fumemdeps.ld_pend_o # also output for use in WaWGrid
111
112 comb += ldstdeps.ld_pend_i.eq(self.ld_i)
113 comb += ldstdeps.st_pend_i.eq(self.st_i)
114 comb += ldstdeps.issue_i.eq(self.fn_issue_i)
115 comb += ldstdeps.load_hit_i.eq(self.load_hit_i)
116 comb += ldstdeps.stwd_hit_i.eq(self.stwd_hit_i)
117 comb += ldstdeps.go_die_i.eq(self.go_die_i)
118 comb += self.storable_o.eq(fumemdeps.storable_o)
119 comb += self.loadable_o.eq(fumemdeps.loadable_o)
120 comb += fumemdeps.ld_pend_i.eq(ldstdeps.ld_hold_st_o)
121 comb += fumemdeps.st_pend_i.eq(ldstdeps.st_hold_ld_o)
122
123 # Connect function issue / arrays, and dest/src1/src2
124
125 comb += fumemdeps.go_st_i.eq(self.stwd_hit_i)
126 comb += fumemdeps.go_ld_i.eq(self.load_hit_i)
127 comb += fumemdeps.go_die_i.eq(self.go_die_i)
128 comb += fumemdeps.issue_i.eq(self.fn_issue_i)
129
130 #comb += self.ld_rsel_o.eq(fumemdeps.ld_rsel_o)
131 #comb += self.st_rsel_o.eq(fumemdeps.st_rsel_o)
132
133 return m
134
135 def __iter__(self):
136 yield self.ld_i
137 yield self.st_i
138 #yield self.g_int_st_pend_o
139 #yield self.g_int_ld_pend_o
140 #yield self.ld_rsel_o
141 #yield self.st_rsel_o
142 yield self.req_rel_i
143 yield self.loadable_o
144 yield self.storable_o
145 yield self.load_hit_i
146 yield self.stwd_hit_i
147 yield self.go_st_i
148 yield self.go_ld_i
149 yield self.go_die_i
150 yield self.req_rel_o
151 yield self.fn_issue_i
152
153 def ports(self):
154 return list(self)
155
156
157 class Scoreboard(Elaboratable):
158 def __init__(self, rwid, n_regs):
159 """ Inputs:
160
161 * :rwid: bit width of register file(s) - both FP and INT
162 * :n_regs: depth of register file(s) - number of FP and INT regs
163 """
164 self.rwid = rwid
165 self.n_regs = n_regs
166
167 # Register Files
168 self.intregs = RegFileArray(rwid, n_regs)
169 self.fpregs = RegFileArray(rwid, n_regs)
170
171 # issue q needs to get at these
172 self.aluissue = IssueUnitGroup(4)
173 self.brissue = IssueUnitGroup(1)
174 # and these
175 self.alu_oper_i = Signal(4, reset_less=True)
176 self.alu_imm_i = Signal(rwid, reset_less=True)
177 self.br_oper_i = Signal(4, reset_less=True)
178 self.br_imm_i = Signal(rwid, reset_less=True)
179
180 # inputs
181 self.int_dest_i = Signal(max=n_regs, reset_less=True) # Dest R# in
182 self.int_src1_i = Signal(max=n_regs, reset_less=True) # oper1 R# in
183 self.int_src2_i = Signal(max=n_regs, reset_less=True) # oper2 R# in
184 self.reg_enable_i = Signal(reset_less=True) # enable reg decode
185
186 # outputs
187 self.issue_o = Signal(reset_less=True) # instruction was accepted
188 self.busy_o = Signal(reset_less=True) # at least one CU is busy
189
190 # for branch speculation experiment. branch_direction = 0 if
191 # the branch hasn't been met yet. 1 indicates "success", 2 is "fail"
192 # branch_succ and branch_fail are requests to have the current
193 # instruction be dependent on the branch unit "shadow" capability.
194 self.branch_succ_i = Signal(reset_less=True)
195 self.branch_fail_i = Signal(reset_less=True)
196 self.branch_direction_o = Signal(2, reset_less=True)
197
198 def elaborate(self, platform):
199 m = Module()
200 comb = m.d.comb
201 sync = m.d.sync
202
203 m.submodules.intregs = self.intregs
204 m.submodules.fpregs = self.fpregs
205
206 # register ports
207 int_dest = self.intregs.write_port("dest")
208 int_src1 = self.intregs.read_port("src1")
209 int_src2 = self.intregs.read_port("src2")
210
211 fp_dest = self.fpregs.write_port("dest")
212 fp_src1 = self.fpregs.read_port("src1")
213 fp_src2 = self.fpregs.read_port("src2")
214
215 # Int ALUs and Comp Units
216 n_int_alus = 5
217 cua = CompUnitALUs(self.rwid, 3)
218 cub = CompUnitBR(self.rwid, 3)
219 m.submodules.cu = cu = CompUnitsBase(self.rwid, [cua, cub])
220 bgt = cub.bgt # get at the branch computation unit
221 br1 = cub.br1
222
223 # Int FUs
224 m.submodules.intfus = intfus = FunctionUnits(self.n_regs, n_int_alus)
225
226 # Count of number of FUs
227 n_intfus = n_int_alus
228 n_fp_fus = 0 # for now
229
230 # Integer Priority Picker 1: Adder + Subtractor
231 intpick1 = GroupPicker(n_intfus) # picks between add, sub, mul and shf
232 m.submodules.intpick1 = intpick1
233
234 # INT/FP Issue Unit
235 regdecode = RegDecode(self.n_regs)
236 m.submodules.regdecode = regdecode
237 issueunit = IssueUnitArray([self.aluissue, self.brissue])
238 m.submodules.issueunit = issueunit
239
240 # Shadow Matrix. currently n_intfus shadows, to be used for
241 # write-after-write hazards. NOTE: there is one extra for branches,
242 # so the shadow width is increased by 1
243 m.submodules.shadows = shadows = ShadowMatrix(n_intfus, n_intfus, True)
244 m.submodules.bshadow = bshadow = ShadowMatrix(n_intfus, 1, False)
245
246 # record previous instruction to cast shadow on current instruction
247 prev_shadow = Signal(n_intfus)
248
249 # Branch Speculation recorder. tracks the success/fail state as
250 # each instruction is issued, so that when the branch occurs the
251 # allow/cancel can be issued as appropriate.
252 m.submodules.specrec = bspec = BranchSpeculationRecord(n_intfus)
253
254 #---------
255 # ok start wiring things together...
256 # "now hear de word of de looord... dem bones dem bones dem dryy bones"
257 # https://www.youtube.com/watch?v=pYb8Wm6-QfA
258 #---------
259
260 #---------
261 # Issue Unit is where it starts. set up some in/outs for this module
262 #---------
263 comb += [ regdecode.dest_i.eq(self.int_dest_i),
264 regdecode.src1_i.eq(self.int_src1_i),
265 regdecode.src2_i.eq(self.int_src2_i),
266 regdecode.enable_i.eq(self.reg_enable_i),
267 self.issue_o.eq(issueunit.issue_o)
268 ]
269
270 # take these to outside (issue needs them)
271 comb += cua.oper_i.eq(self.alu_oper_i)
272 comb += cua.imm_i.eq(self.alu_imm_i)
273 comb += cub.oper_i.eq(self.br_oper_i)
274 comb += cub.imm_i.eq(self.br_imm_i)
275
276 # TODO: issueunit.f (FP)
277
278 # and int function issue / busy arrays, and dest/src1/src2
279 comb += intfus.dest_i.eq(regdecode.dest_o)
280 comb += intfus.src1_i.eq(regdecode.src1_o)
281 comb += intfus.src2_i.eq(regdecode.src2_o)
282
283 fn_issue_o = issueunit.fn_issue_o
284
285 comb += intfus.fn_issue_i.eq(fn_issue_o)
286 comb += issueunit.busy_i.eq(cu.busy_o)
287 comb += self.busy_o.eq(cu.busy_o.bool())
288
289 #---------
290 # merge shadow matrices outputs
291 #---------
292
293 # these are explained in ShadowMatrix docstring, and are to be
294 # connected to the FUReg and FUFU Matrices, to get them to reset
295 anydie = Signal(n_intfus, reset_less=True)
296 allshadown = Signal(n_intfus, reset_less=True)
297 shreset = Signal(n_intfus, reset_less=True)
298 comb += allshadown.eq(shadows.shadown_o & bshadow.shadown_o)
299 comb += anydie.eq(shadows.go_die_o | bshadow.go_die_o)
300 comb += shreset.eq(bspec.match_g_o | bspec.match_f_o)
301
302 #---------
303 # connect fu-fu matrix
304 #---------
305
306 # Group Picker... done manually for now.
307 go_rd_o = intpick1.go_rd_o
308 go_wr_o = intpick1.go_wr_o
309 go_rd_i = intfus.go_rd_i
310 go_wr_i = intfus.go_wr_i
311 go_die_i = intfus.go_die_i
312 # NOTE: connect to the shadowed versions so that they can "die" (reset)
313 comb += go_rd_i[0:n_intfus].eq(go_rd_o[0:n_intfus]) # rd
314 comb += go_wr_i[0:n_intfus].eq(go_wr_o[0:n_intfus]) # wr
315 comb += go_die_i[0:n_intfus].eq(anydie[0:n_intfus]) # die
316
317 # Connect Picker
318 #---------
319 comb += intpick1.rd_rel_i[0:n_intfus].eq(cu.rd_rel_o[0:n_intfus])
320 comb += intpick1.req_rel_i[0:n_intfus].eq(cu.req_rel_o[0:n_intfus])
321 int_rd_o = intfus.readable_o
322 int_wr_o = intfus.writable_o
323 comb += intpick1.readable_i[0:n_intfus].eq(int_rd_o[0:n_intfus])
324 comb += intpick1.writable_i[0:n_intfus].eq(int_wr_o[0:n_intfus])
325
326 #---------
327 # Shadow Matrix
328 #---------
329
330 comb += shadows.issue_i.eq(fn_issue_o)
331 #comb += shadows.reset_i[0:n_intfus].eq(bshadow.go_die_o[0:n_intfus])
332 comb += shadows.reset_i[0:n_intfus].eq(bshadow.go_die_o[0:n_intfus])
333 #---------
334 # NOTE; this setup is for the instruction order preservation...
335
336 # connect shadows / go_dies to Computation Units
337 comb += cu.shadown_i[0:n_intfus].eq(allshadown)
338 comb += cu.go_die_i[0:n_intfus].eq(anydie)
339
340 # ok connect first n_int_fu shadows to busy lines, to create an
341 # instruction-order linked-list-like arrangement, using a bit-matrix
342 # (instead of e.g. a ring buffer).
343 # XXX TODO
344
345 # when written, the shadow can be cancelled (and was good)
346 for i in range(n_intfus):
347 comb += shadows.s_good_i[i][0:n_intfus].eq(go_wr_o[0:n_intfus])
348
349 # *previous* instruction shadows *current* instruction, and, obviously,
350 # if the previous is completed (!busy) don't cast the shadow!
351 comb += prev_shadow.eq(~fn_issue_o & cu.busy_o)
352 for i in range(n_intfus):
353 comb += shadows.shadow_i[i][0:n_intfus].eq(prev_shadow)
354
355 #---------
356 # ... and this is for branch speculation. it uses the extra bit
357 # tacked onto the ShadowMatrix (hence shadow_wid=n_intfus+1)
358 # only needs to set shadow_i, s_fail_i and s_good_i
359
360 # issue captures shadow_i (if enabled)
361 comb += bshadow.reset_i[0:n_intfus].eq(shreset[0:n_intfus])
362
363 bactive = Signal(reset_less=True)
364 comb += bactive.eq((bspec.active_i | br1.issue_i) & ~br1.go_wr_i)
365
366 # instruction being issued (fn_issue_o) has a shadow cast by the branch
367 with m.If(bactive & (self.branch_succ_i | self.branch_fail_i)):
368 comb += bshadow.issue_i.eq(fn_issue_o)
369 for i in range(n_intfus):
370 with m.If(fn_issue_o & (Const(1<<i))):
371 comb += bshadow.shadow_i[i][0].eq(1)
372
373 # finally, we need an indicator to the test infrastructure as to
374 # whether the branch succeeded or failed, plus, link up to the
375 # "recorder" of whether the instruction was under shadow or not
376
377 with m.If(br1.issue_i):
378 sync += bspec.active_i.eq(1)
379 with m.If(self.branch_succ_i):
380 comb += bspec.good_i.eq(fn_issue_o & 0x1f)
381 with m.If(self.branch_fail_i):
382 comb += bspec.fail_i.eq(fn_issue_o & 0x1f)
383
384 # branch is active (TODO: a better signal: this is over-using the
385 # go_write signal - actually the branch should not be "writing")
386 with m.If(br1.go_wr_i):
387 sync += self.branch_direction_o.eq(br1.data_o+Const(1, 2))
388 sync += bspec.active_i.eq(0)
389 comb += bspec.br_i.eq(1)
390 # branch occurs if data == 1, failed if data == 0
391 comb += bspec.br_ok_i.eq(br1.data_o == 1)
392 for i in range(n_intfus):
393 # *expected* direction of the branch matched against *actual*
394 comb += bshadow.s_good_i[i][0].eq(bspec.match_g_o[i])
395 # ... or it didn't
396 comb += bshadow.s_fail_i[i][0].eq(bspec.match_f_o[i])
397
398 #---------
399 # Connect Register File(s)
400 #---------
401 comb += int_dest.wen.eq(intfus.dest_rsel_o)
402 comb += int_src1.ren.eq(intfus.src1_rsel_o)
403 comb += int_src2.ren.eq(intfus.src2_rsel_o)
404
405 # connect ALUs to regfule
406 comb += int_dest.data_i.eq(cu.data_o)
407 comb += cu.src1_i.eq(int_src1.data_o)
408 comb += cu.src2_i.eq(int_src2.data_o)
409
410 # connect ALU Computation Units
411 comb += cu.go_rd_i[0:n_intfus].eq(go_rd_o[0:n_intfus])
412 comb += cu.go_wr_i[0:n_intfus].eq(go_wr_o[0:n_intfus])
413 comb += cu.issue_i[0:n_intfus].eq(fn_issue_o[0:n_intfus])
414
415 return m
416
417 def __iter__(self):
418 yield from self.intregs
419 yield from self.fpregs
420 yield self.int_dest_i
421 yield self.int_src1_i
422 yield self.int_src2_i
423 yield self.issue_o
424 yield self.branch_succ_i
425 yield self.branch_fail_i
426 yield self.branch_direction_o
427
428 def ports(self):
429 return list(self)
430
431
432
433
434 def int_instr(dut, op, imm, src1, src2, dest, branch_success, branch_fail):
435 yield from disable_issue(dut)
436 yield dut.int_dest_i.eq(dest)
437 yield dut.int_src1_i.eq(src1)
438 yield dut.int_src2_i.eq(src2)
439 if (op & (0x3<<2)) != 0: # branch
440 yield dut.brissue.insn_i.eq(1)
441 yield dut.br_oper_i.eq(Const(op & 0x3, 2))
442 yield dut.br_imm_i.eq(imm)
443 dut_issue = dut.brissue
444 else:
445 yield dut.aluissue.insn_i.eq(1)
446 yield dut.alu_oper_i.eq(Const(op & 0x3, 2))
447 yield dut.alu_imm_i.eq(imm)
448 dut_issue = dut.aluissue
449 yield dut.reg_enable_i.eq(1)
450
451 # these indicate that the instruction is to be made shadow-dependent on
452 # (either) branch success or branch fail
453 yield dut.branch_fail_i.eq(branch_fail)
454 yield dut.branch_succ_i.eq(branch_success)
455
456 yield
457 yield from wait_for_issue(dut, dut_issue)
458
459
460 def print_reg(dut, rnums):
461 rs = []
462 for rnum in rnums:
463 reg = yield dut.intregs.regs[rnum].reg
464 rs.append("%x" % reg)
465 rnums = map(str, rnums)
466 print ("reg %s: %s" % (','.join(rnums), ','.join(rs)))
467
468
469 def create_random_ops(dut, n_ops, shadowing=False, max_opnums=3):
470 insts = []
471 for i in range(n_ops):
472 src1 = randint(1, dut.n_regs-1)
473 src2 = randint(1, dut.n_regs-1)
474 imm = randint(1, (1<<dut.rwid)-1)
475 dest = randint(1, dut.n_regs-1)
476 op = randint(0, max_opnums)
477 opi = 0 if randint(0, 2) else 1 # set true if random is nonzero
478
479 if shadowing:
480 insts.append((src1, src2, dest, op, opi, imm, (0, 0)))
481 else:
482 insts.append((src1, src2, dest, op, opi, imm))
483 return insts
484
485
486
487 def scoreboard_sim(dut, alusim):
488
489 seed(0)
490
491 for i in range(50):
492
493 # set random values in the registers
494 for i in range(1, dut.n_regs):
495 val = randint(0, (1<<alusim.rwidth)-1)
496 #val = 31+i*3
497 #val = i
498 yield dut.intregs.regs[i].reg.eq(val)
499 alusim.setval(i, val)
500
501 # create some instructions (some random, some regression tests)
502 instrs = []
503 if True:
504 instrs = create_random_ops(dut, 15, True, 4)
505
506 if False:
507 instrs.append( (1, 2, 2, 1, 1, 20, (0, 0)) )
508
509 if False:
510 instrs.append( (7, 3, 2, 4, (0, 0)) )
511 instrs.append( (7, 6, 6, 2, (0, 0)) )
512 instrs.append( (1, 7, 2, 2, (0, 0)) )
513
514 if False:
515 instrs.append((2, 3, 3, 0, 0, 0, (0, 0)))
516 instrs.append((5, 3, 3, 1, 0, 0, (0, 0)))
517 instrs.append((3, 5, 5, 2, 0, 0, (0, 0)))
518 instrs.append((5, 3, 3, 3, 0, 0, (0, 0)))
519 instrs.append((3, 5, 5, 0, 0, 0, (0, 0)))
520
521 if False:
522 instrs.append( (3, 3, 4, 0, 0, 13979, (0, 0)))
523 instrs.append( (6, 4, 1, 2, 0, 40976, (0, 0)))
524 instrs.append( (1, 4, 7, 4, 1, 23652, (0, 0)))
525
526 if False:
527 instrs.append((5, 6, 2, 1))
528 instrs.append((2, 2, 4, 0))
529 #instrs.append((2, 2, 3, 1))
530
531 if False:
532 instrs.append((2, 1, 2, 3))
533
534 if False:
535 instrs.append((2, 6, 2, 1))
536 instrs.append((2, 1, 2, 0))
537
538 if False:
539 instrs.append((1, 2, 7, 2))
540 instrs.append((7, 1, 5, 0))
541 instrs.append((4, 4, 1, 1))
542
543 if False:
544 instrs.append((5, 6, 2, 2))
545 instrs.append((1, 1, 4, 1))
546 instrs.append((6, 5, 3, 0))
547
548 if False:
549 # Write-after-Write Hazard
550 instrs.append( (3, 6, 7, 2) )
551 instrs.append( (4, 4, 7, 1) )
552
553 if False:
554 # self-read/write-after-write followed by Read-after-Write
555 instrs.append((1, 1, 1, 1))
556 instrs.append((1, 5, 3, 0))
557
558 if False:
559 # Read-after-Write followed by self-read-after-write
560 instrs.append((5, 6, 1, 2))
561 instrs.append((1, 1, 1, 1))
562
563 if False:
564 # self-read-write sandwich
565 instrs.append((5, 6, 1, 2))
566 instrs.append((1, 1, 1, 1))
567 instrs.append((1, 5, 3, 0))
568
569 if False:
570 # very weird failure
571 instrs.append( (5, 2, 5, 2) )
572 instrs.append( (2, 6, 3, 0) )
573 instrs.append( (4, 2, 2, 1) )
574
575 if False:
576 v1 = 4
577 yield dut.intregs.regs[5].reg.eq(v1)
578 alusim.setval(5, v1)
579 yield dut.intregs.regs[3].reg.eq(5)
580 alusim.setval(3, 5)
581 instrs.append((5, 3, 3, 4, (0, 0)))
582 instrs.append((4, 2, 1, 2, (0, 1)))
583
584 if False:
585 v1 = 6
586 yield dut.intregs.regs[5].reg.eq(v1)
587 alusim.setval(5, v1)
588 yield dut.intregs.regs[3].reg.eq(5)
589 alusim.setval(3, 5)
590 instrs.append((5, 3, 3, 4, (0, 0)))
591 instrs.append((4, 2, 1, 2, (1, 0)))
592
593 if False:
594 instrs.append( (4, 3, 5, 1, 0, (0, 0)) )
595 instrs.append( (5, 2, 3, 1, 0, (0, 0)) )
596 instrs.append( (7, 1, 5, 2, 0, (0, 0)) )
597 instrs.append( (5, 6, 6, 4, 0, (0, 0)) )
598 instrs.append( (7, 5, 2, 2, 0, (1, 0)) )
599 instrs.append( (1, 7, 5, 0, 0, (0, 1)) )
600 instrs.append( (1, 6, 1, 2, 0, (1, 0)) )
601 instrs.append( (1, 6, 7, 3, 0, (0, 0)) )
602 instrs.append( (6, 7, 7, 0, 0, (0, 0)) )
603
604 # issue instruction(s), wait for issue to be free before proceeding
605 for i, instr in enumerate(instrs):
606 src1, src2, dest, op, opi, imm, (br_ok, br_fail) = instr
607
608 print ("instr %d: (%d, %d, %d, %d, %d, %d)" % \
609 (i, src1, src2, dest, op, opi, imm))
610 alusim.op(op, opi, imm, src1, src2, dest)
611 yield from instr_q(dut, op, opi, imm, src1, src2, dest,
612 br_ok, br_fail)
613
614 # wait for all instructions to stop before checking
615 while True:
616 iqlen = yield dut.qlen_o
617 if iqlen == 0:
618 break
619 yield
620 yield
621 yield
622 yield
623 yield
624 yield from wait_for_busy_clear(dut)
625
626 # check status
627 yield from alusim.check(dut)
628 yield from alusim.dump(dut)
629
630
631 def test_scoreboard():
632 dut = IssueToScoreboard(2, 1, 1, 16, 8, 8)
633 alusim = RegSim(16, 8)
634 memsim = MemSim(16, 16)
635 vl = rtlil.convert(dut, ports=dut.ports())
636 with open("test_scoreboard6600.il", "w") as f:
637 f.write(vl)
638
639 run_simulation(dut, scoreboard_sim(dut, alusim),
640 vcd_name='test_scoreboard6600.vcd')
641
642 #run_simulation(dut, scoreboard_branch_sim(dut, alusim),
643 # vcd_name='test_scoreboard6600.vcd')
644
645
646 def mem_sim(dut):
647 yield dut.ld_i.eq(0x1)
648 yield dut.fn_issue_i.eq(0x1)
649 yield
650 #yield dut.ld_i.eq(0x0)
651 yield dut.st_i.eq(0x2)
652 yield dut.fn_issue_i.eq(0x2)
653 yield
654 #yield dut.st_i.eq(0x0)
655 yield dut.fn_issue_i.eq(0x0)
656 yield
657
658 yield dut.load_hit_i.eq(0x1)
659 yield
660 yield dut.load_hit_i.eq(0x0)
661 yield
662 yield dut.stwd_hit_i.eq(0x2)
663 yield
664 yield dut.stwd_hit_i.eq(0x0)
665 yield
666
667
668 def test_mem_fus():
669 dut = MemFunctionUnits(3)
670 vl = rtlil.convert(dut, ports=dut.ports())
671 with open("test_mem_fus.il", "w") as f:
672 f.write(vl)
673
674 run_simulation(dut, mem_sim(dut),
675 vcd_name='test_mem_fus.vcd')
676
677
678 if __name__ == '__main__':
679 test_mem_fus()