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
5 from regfile
.regfile
import RegFileArray
, treereduce
6 from scoreboard
.fu_fu_matrix
import FUFUDepMatrix
7 from scoreboard
.global_pending
import GlobalPending
8 from scoreboard
.group_picker
import GroupPicker
9 from scoreboard
.issue_unit
import IssueUnitGroup
, IssueUnitArray
, RegDecode
10 from scoreboard
.shadow
import ShadowMatrix
, BranchSpeculationRecord
11 from scoreboard
.mdm
import FUMemMatchMatrix
12 from nmutil
.latch
import SRLatch
13 from nmutil
.nmoperator
import eq
15 from random
import randint
, seed
16 from copy
import deepcopy
20 class Memory(Elaboratable
):
21 def __init__(self
, regwid
, addrw
):
22 self
.ddepth
= regwid
/8
23 depth
= (1<<addrw
) / self
.ddepth
24 self
.adr
= Signal(addrw
)
25 self
.dat_r
= Signal(regwid
)
26 self
.dat_w
= Signal(regwid
)
28 self
.mem
= Memory(width
=regwid
, depth
=depth
, init
=range(0, depth
))
30 def elaborate(self
, platform
):
32 m
.submodules
.rdport
= rdport
= self
.mem
.read_port()
33 m
.submodules
.wrport
= wrport
= self
.mem
.write_port()
35 rdport
.addr
.eq(self
.adr
[self
.ddepth
:]), # ignore low bits
36 self
.dat_r
.eq(rdport
.data
),
37 wrport
.addr
.eq(self
.adr
),
38 wrport
.data
.eq(self
.dat_w
),
39 wrport
.en
.eq(self
.we
),
45 def __init__(self
, regwid
, addrw
):
47 self
.ddepth
= regwid
//8
48 depth
= (1<<addrw
) // self
.ddepth
49 self
.mem
= list(range(0, depth
))
52 return self
.mem
[addr
>>self
.ddepth
]
54 def st(self
, addr
, data
):
55 self
.mem
[addr
>>self
.ddepth
] = data
& ((1<<self
.regwid
)-1)
59 class MemFunctionUnits(Elaboratable
):
61 def __init__(self
, n_ldsts
, addrbitwid
):
62 self
.n_ldsts
= n_ldsts
63 self
.bitwid
= addrbitwid
65 self
.st_i
= Signal(n_ldsts
, reset_less
=True) # Dest R# in
66 self
.ld_i
= Signal(n_ldsts
, reset_less
=True) # oper1 R# in
68 self
.g_int_ld_pend_o
= Signal(n_ldsts
, reset_less
=True)
69 self
.g_int_st_pend_o
= Signal(n_ldsts
, reset_less
=True)
71 self
.st_rsel_o
= Signal(n_ldsts
, reset_less
=True) # dest reg (bot)
72 self
.ld_rsel_o
= Signal(n_ldsts
, reset_less
=True) # src1 reg (bot)
74 self
.loadable_o
= Signal(n_ldsts
, reset_less
=True)
75 self
.storable_o
= Signal(n_ldsts
, reset_less
=True)
77 self
.go_ld_i
= Signal(n_ldsts
, reset_less
=True)
78 self
.go_st_i
= Signal(n_ldsts
, reset_less
=True)
79 self
.go_die_i
= Signal(n_ldsts
, reset_less
=True)
80 self
.fn_issue_i
= Signal(n_ldsts
, reset_less
=True)
83 self
.addrs_i
= Array(Signal(self
.bitwid
, name
="addrs_i%d" % i
) \
84 for i
in range(n_ldsts
))
85 self
.addr_we_i
= Signal(n_ldsts
) # write-enable for incoming address
86 self
.addr_en_i
= Signal(n_ldsts
) # address activated (0 == ignore)
88 # Note: FURegs st_pend_o is also outputted from here, for use in WaWGrid
90 def elaborate(self
, platform
):
97 # Integer FU-FU Dep Matrix
98 intfudeps
= FUFUDepMatrix(n_fus
, n_fus
)
99 m
.submodules
.intfudeps
= intfudeps
100 # Integer FU-Reg Dep Matrix
101 intregdeps
= FUMemMatchMatrix(n_fus
, self
.bitwid
)
102 m
.submodules
.intregdeps
= intregdeps
104 # ok, because we do not know in advance what the AGEN (address gen)
105 # is, we have to make a transitive dependency set. i.e. the LD
106 # (or ST) being requested now must depend on ALL prior LDs *AND* STs.
107 # these get dropped very rapidly once AGEN is carried out.
110 # connect fureg matrix as a mem system
111 comb
+= self
.g_int_ld_pend_o
.eq(intregdeps
.v_rd_rsel_o
)
112 comb
+= self
.g_int_st_pend_o
.eq(intregdeps
.v_wr_rsel_o
)
114 comb
+= intregdeps
.rd_pend_i
.eq(intregdeps
.v_rd_rsel_o
)
115 comb
+= intregdeps
.wr_pend_i
.eq(intregdeps
.v_wr_rsel_o
)
117 comb
+= intfudeps
.rd_pend_i
.eq(intregdeps
.rd_pend_o
)
118 comb
+= intfudeps
.wr_pend_i
.eq(intregdeps
.wr_pend_o
)
119 self
.st_pend_o
= intregdeps
.wr_pend_o
# also output for use in WaWGrid
121 comb
+= intfudeps
.issue_i
.eq(self
.fn_issue_i
)
122 comb
+= intfudeps
.go_rd_i
.eq(self
.go_ld_i
)
123 comb
+= intfudeps
.go_wr_i
.eq(self
.go_st_i
)
124 comb
+= intfudeps
.go_die_i
.eq(self
.go_die_i
)
125 comb
+= self
.loadable_o
.eq(intfudeps
.readable_o
)
126 comb
+= self
.storable_o
.eq(intfudeps
.writable_o
)
128 # Connect function issue / arrays, and dest/src1/src2
129 comb
+= intregdeps
.dest_i
.eq(self
.st_i
)
130 comb
+= intregdeps
.src_i
[0].eq(self
.ld_i
)
132 comb
+= intregdeps
.go_rd_i
.eq(self
.go_ld_i
)
133 comb
+= intregdeps
.go_wr_i
.eq(self
.go_st_i
)
134 comb
+= intregdeps
.go_die_i
.eq(self
.go_die_i
)
135 comb
+= intregdeps
.issue_i
.eq(self
.fn_issue_i
)
137 comb
+= self
.st_rsel_o
.eq(intregdeps
.dest_rsel_o
)
138 comb
+= self
.ld_rsel_o
.eq(intregdeps
.src_rsel_o
[0])
140 # connect address matching: these get connected to the Addr CUs
141 for i
in range(self
.n_ldsts
):
142 comb
+= intregdeps
.addrs_i
[i
].eq(self
.addrs_i
[i
])
143 comb
+= intregdeps
.addr_we_i
.eq(self
.addr_we_i
)
144 comb
+= intregdeps
.addr_en_i
.eq(self
.addr_en_i
)
151 yield self
.g_int_st_pend_o
152 yield self
.g_int_ld_pend_o
155 yield self
.loadable_o
156 yield self
.storable_o
160 yield self
.fn_issue_i
161 yield from self
.addrs_i
169 class Scoreboard(Elaboratable
):
170 def __init__(self
, rwid
, n_regs
):
173 * :rwid: bit width of register file(s) - both FP and INT
174 * :n_regs: depth of register file(s) - number of FP and INT regs
180 self
.intregs
= RegFileArray(rwid
, n_regs
)
181 self
.fpregs
= RegFileArray(rwid
, n_regs
)
183 # issue q needs to get at these
184 self
.aluissue
= IssueUnitGroup(4)
185 self
.brissue
= IssueUnitGroup(1)
187 self
.alu_oper_i
= Signal(4, reset_less
=True)
188 self
.alu_imm_i
= Signal(rwid
, reset_less
=True)
189 self
.br_oper_i
= Signal(4, reset_less
=True)
190 self
.br_imm_i
= Signal(rwid
, reset_less
=True)
193 self
.int_dest_i
= Signal(max=n_regs
, reset_less
=True) # Dest R# in
194 self
.int_src1_i
= Signal(max=n_regs
, reset_less
=True) # oper1 R# in
195 self
.int_src2_i
= Signal(max=n_regs
, reset_less
=True) # oper2 R# in
196 self
.reg_enable_i
= Signal(reset_less
=True) # enable reg decode
199 self
.issue_o
= Signal(reset_less
=True) # instruction was accepted
200 self
.busy_o
= Signal(reset_less
=True) # at least one CU is busy
202 # for branch speculation experiment. branch_direction = 0 if
203 # the branch hasn't been met yet. 1 indicates "success", 2 is "fail"
204 # branch_succ and branch_fail are requests to have the current
205 # instruction be dependent on the branch unit "shadow" capability.
206 self
.branch_succ_i
= Signal(reset_less
=True)
207 self
.branch_fail_i
= Signal(reset_less
=True)
208 self
.branch_direction_o
= Signal(2, reset_less
=True)
210 def elaborate(self
, platform
):
215 m
.submodules
.intregs
= self
.intregs
216 m
.submodules
.fpregs
= self
.fpregs
219 int_dest
= self
.intregs
.write_port("dest")
220 int_src1
= self
.intregs
.read_port("src1")
221 int_src2
= self
.intregs
.read_port("src2")
223 fp_dest
= self
.fpregs
.write_port("dest")
224 fp_src1
= self
.fpregs
.read_port("src1")
225 fp_src2
= self
.fpregs
.read_port("src2")
227 # Int ALUs and Comp Units
229 cua
= CompUnitALUs(self
.rwid
, 3)
230 cub
= CompUnitBR(self
.rwid
, 3)
231 m
.submodules
.cu
= cu
= CompUnitsBase(self
.rwid
, [cua
, cub
])
232 bgt
= cub
.bgt
# get at the branch computation unit
236 m
.submodules
.intfus
= intfus
= FunctionUnits(self
.n_regs
, n_int_alus
)
238 # Count of number of FUs
239 n_intfus
= n_int_alus
240 n_fp_fus
= 0 # for now
242 # Integer Priority Picker 1: Adder + Subtractor
243 intpick1
= GroupPicker(n_intfus
) # picks between add, sub, mul and shf
244 m
.submodules
.intpick1
= intpick1
247 regdecode
= RegDecode(self
.n_regs
)
248 m
.submodules
.regdecode
= regdecode
249 issueunit
= IssueUnitArray([self
.aluissue
, self
.brissue
])
250 m
.submodules
.issueunit
= issueunit
252 # Shadow Matrix. currently n_intfus shadows, to be used for
253 # write-after-write hazards. NOTE: there is one extra for branches,
254 # so the shadow width is increased by 1
255 m
.submodules
.shadows
= shadows
= ShadowMatrix(n_intfus
, n_intfus
, True)
256 m
.submodules
.bshadow
= bshadow
= ShadowMatrix(n_intfus
, 1, False)
258 # record previous instruction to cast shadow on current instruction
259 prev_shadow
= Signal(n_intfus
)
261 # Branch Speculation recorder. tracks the success/fail state as
262 # each instruction is issued, so that when the branch occurs the
263 # allow/cancel can be issued as appropriate.
264 m
.submodules
.specrec
= bspec
= BranchSpeculationRecord(n_intfus
)
267 # ok start wiring things together...
268 # "now hear de word of de looord... dem bones dem bones dem dryy bones"
269 # https://www.youtube.com/watch?v=pYb8Wm6-QfA
273 # Issue Unit is where it starts. set up some in/outs for this module
275 comb
+= [ regdecode
.dest_i
.eq(self
.int_dest_i
),
276 regdecode
.src1_i
.eq(self
.int_src1_i
),
277 regdecode
.src2_i
.eq(self
.int_src2_i
),
278 regdecode
.enable_i
.eq(self
.reg_enable_i
),
279 self
.issue_o
.eq(issueunit
.issue_o
)
282 # take these to outside (issue needs them)
283 comb
+= cua
.oper_i
.eq(self
.alu_oper_i
)
284 comb
+= cua
.imm_i
.eq(self
.alu_imm_i
)
285 comb
+= cub
.oper_i
.eq(self
.br_oper_i
)
286 comb
+= cub
.imm_i
.eq(self
.br_imm_i
)
288 # TODO: issueunit.f (FP)
290 # and int function issue / busy arrays, and dest/src1/src2
291 comb
+= intfus
.dest_i
.eq(regdecode
.dest_o
)
292 comb
+= intfus
.src1_i
.eq(regdecode
.src1_o
)
293 comb
+= intfus
.src2_i
.eq(regdecode
.src2_o
)
295 fn_issue_o
= issueunit
.fn_issue_o
297 comb
+= intfus
.fn_issue_i
.eq(fn_issue_o
)
298 comb
+= issueunit
.busy_i
.eq(cu
.busy_o
)
299 comb
+= self
.busy_o
.eq(cu
.busy_o
.bool())
302 # merge shadow matrices outputs
305 # these are explained in ShadowMatrix docstring, and are to be
306 # connected to the FUReg and FUFU Matrices, to get them to reset
307 anydie
= Signal(n_intfus
, reset_less
=True)
308 allshadown
= Signal(n_intfus
, reset_less
=True)
309 shreset
= Signal(n_intfus
, reset_less
=True)
310 comb
+= allshadown
.eq(shadows
.shadown_o
& bshadow
.shadown_o
)
311 comb
+= anydie
.eq(shadows
.go_die_o | bshadow
.go_die_o
)
312 comb
+= shreset
.eq(bspec
.match_g_o | bspec
.match_f_o
)
315 # connect fu-fu matrix
318 # Group Picker... done manually for now.
319 go_rd_o
= intpick1
.go_rd_o
320 go_wr_o
= intpick1
.go_wr_o
321 go_rd_i
= intfus
.go_rd_i
322 go_wr_i
= intfus
.go_wr_i
323 go_die_i
= intfus
.go_die_i
324 # NOTE: connect to the shadowed versions so that they can "die" (reset)
325 comb
+= go_rd_i
[0:n_intfus
].eq(go_rd_o
[0:n_intfus
]) # rd
326 comb
+= go_wr_i
[0:n_intfus
].eq(go_wr_o
[0:n_intfus
]) # wr
327 comb
+= go_die_i
[0:n_intfus
].eq(anydie
[0:n_intfus
]) # die
331 comb
+= intpick1
.rd_rel_i
[0:n_intfus
].eq(cu
.rd_rel_o
[0:n_intfus
])
332 comb
+= intpick1
.req_rel_i
[0:n_intfus
].eq(cu
.req_rel_o
[0:n_intfus
])
333 int_rd_o
= intfus
.readable_o
334 int_wr_o
= intfus
.writable_o
335 comb
+= intpick1
.readable_i
[0:n_intfus
].eq(int_rd_o
[0:n_intfus
])
336 comb
+= intpick1
.writable_i
[0:n_intfus
].eq(int_wr_o
[0:n_intfus
])
342 comb
+= shadows
.issue_i
.eq(fn_issue_o
)
343 #comb += shadows.reset_i[0:n_intfus].eq(bshadow.go_die_o[0:n_intfus])
344 comb
+= shadows
.reset_i
[0:n_intfus
].eq(bshadow
.go_die_o
[0:n_intfus
])
346 # NOTE; this setup is for the instruction order preservation...
348 # connect shadows / go_dies to Computation Units
349 comb
+= cu
.shadown_i
[0:n_intfus
].eq(allshadown
)
350 comb
+= cu
.go_die_i
[0:n_intfus
].eq(anydie
)
352 # ok connect first n_int_fu shadows to busy lines, to create an
353 # instruction-order linked-list-like arrangement, using a bit-matrix
354 # (instead of e.g. a ring buffer).
357 # when written, the shadow can be cancelled (and was good)
358 for i
in range(n_intfus
):
359 comb
+= shadows
.s_good_i
[i
][0:n_intfus
].eq(go_wr_o
[0:n_intfus
])
361 # *previous* instruction shadows *current* instruction, and, obviously,
362 # if the previous is completed (!busy) don't cast the shadow!
363 comb
+= prev_shadow
.eq(~fn_issue_o
& cu
.busy_o
)
364 for i
in range(n_intfus
):
365 comb
+= shadows
.shadow_i
[i
][0:n_intfus
].eq(prev_shadow
)
368 # ... and this is for branch speculation. it uses the extra bit
369 # tacked onto the ShadowMatrix (hence shadow_wid=n_intfus+1)
370 # only needs to set shadow_i, s_fail_i and s_good_i
372 # issue captures shadow_i (if enabled)
373 comb
+= bshadow
.reset_i
[0:n_intfus
].eq(shreset
[0:n_intfus
])
375 bactive
= Signal(reset_less
=True)
376 comb
+= bactive
.eq((bspec
.active_i | br1
.issue_i
) & ~br1
.go_wr_i
)
378 # instruction being issued (fn_issue_o) has a shadow cast by the branch
379 with m
.If(bactive
& (self
.branch_succ_i | self
.branch_fail_i
)):
380 comb
+= bshadow
.issue_i
.eq(fn_issue_o
)
381 for i
in range(n_intfus
):
382 with m
.If(fn_issue_o
& (Const(1<<i
))):
383 comb
+= bshadow
.shadow_i
[i
][0].eq(1)
385 # finally, we need an indicator to the test infrastructure as to
386 # whether the branch succeeded or failed, plus, link up to the
387 # "recorder" of whether the instruction was under shadow or not
389 with m
.If(br1
.issue_i
):
390 sync
+= bspec
.active_i
.eq(1)
391 with m
.If(self
.branch_succ_i
):
392 comb
+= bspec
.good_i
.eq(fn_issue_o
& 0x1f)
393 with m
.If(self
.branch_fail_i
):
394 comb
+= bspec
.fail_i
.eq(fn_issue_o
& 0x1f)
396 # branch is active (TODO: a better signal: this is over-using the
397 # go_write signal - actually the branch should not be "writing")
398 with m
.If(br1
.go_wr_i
):
399 sync
+= self
.branch_direction_o
.eq(br1
.data_o
+Const(1, 2))
400 sync
+= bspec
.active_i
.eq(0)
401 comb
+= bspec
.br_i
.eq(1)
402 # branch occurs if data == 1, failed if data == 0
403 comb
+= bspec
.br_ok_i
.eq(br1
.data_o
== 1)
404 for i
in range(n_intfus
):
405 # *expected* direction of the branch matched against *actual*
406 comb
+= bshadow
.s_good_i
[i
][0].eq(bspec
.match_g_o
[i
])
408 comb
+= bshadow
.s_fail_i
[i
][0].eq(bspec
.match_f_o
[i
])
411 # Connect Register File(s)
413 comb
+= int_dest
.wen
.eq(intfus
.dest_rsel_o
)
414 comb
+= int_src1
.ren
.eq(intfus
.src1_rsel_o
)
415 comb
+= int_src2
.ren
.eq(intfus
.src2_rsel_o
)
417 # connect ALUs to regfule
418 comb
+= int_dest
.data_i
.eq(cu
.data_o
)
419 comb
+= cu
.src1_i
.eq(int_src1
.data_o
)
420 comb
+= cu
.src2_i
.eq(int_src2
.data_o
)
422 # connect ALU Computation Units
423 comb
+= cu
.go_rd_i
[0:n_intfus
].eq(go_rd_o
[0:n_intfus
])
424 comb
+= cu
.go_wr_i
[0:n_intfus
].eq(go_wr_o
[0:n_intfus
])
425 comb
+= cu
.issue_i
[0:n_intfus
].eq(fn_issue_o
[0:n_intfus
])
430 yield from self
.intregs
431 yield from self
.fpregs
432 yield self
.int_dest_i
433 yield self
.int_src1_i
434 yield self
.int_src2_i
436 yield self
.branch_succ_i
437 yield self
.branch_fail_i
438 yield self
.branch_direction_o
446 def int_instr(dut
, op
, imm
, src1
, src2
, dest
, branch_success
, branch_fail
):
447 yield from disable_issue(dut
)
448 yield dut
.int_dest_i
.eq(dest
)
449 yield dut
.int_src1_i
.eq(src1
)
450 yield dut
.int_src2_i
.eq(src2
)
451 if (op
& (0x3<<2)) != 0: # branch
452 yield dut
.brissue
.insn_i
.eq(1)
453 yield dut
.br_oper_i
.eq(Const(op
& 0x3, 2))
454 yield dut
.br_imm_i
.eq(imm
)
455 dut_issue
= dut
.brissue
457 yield dut
.aluissue
.insn_i
.eq(1)
458 yield dut
.alu_oper_i
.eq(Const(op
& 0x3, 2))
459 yield dut
.alu_imm_i
.eq(imm
)
460 dut_issue
= dut
.aluissue
461 yield dut
.reg_enable_i
.eq(1)
463 # these indicate that the instruction is to be made shadow-dependent on
464 # (either) branch success or branch fail
465 yield dut
.branch_fail_i
.eq(branch_fail
)
466 yield dut
.branch_succ_i
.eq(branch_success
)
469 yield from wait_for_issue(dut
, dut_issue
)
472 def print_reg(dut
, rnums
):
475 reg
= yield dut
.intregs
.regs
[rnum
].reg
476 rs
.append("%x" % reg
)
477 rnums
= map(str, rnums
)
478 print ("reg %s: %s" % (','.join(rnums
), ','.join(rs
)))
481 def create_random_ops(dut
, n_ops
, shadowing
=False, max_opnums
=3):
483 for i
in range(n_ops
):
484 src1
= randint(1, dut
.n_regs
-1)
485 src2
= randint(1, dut
.n_regs
-1)
486 imm
= randint(1, (1<<dut
.rwid
)-1)
487 dest
= randint(1, dut
.n_regs
-1)
488 op
= randint(0, max_opnums
)
489 opi
= 0 if randint(0, 2) else 1 # set true if random is nonzero
492 insts
.append((src1
, src2
, dest
, op
, opi
, imm
, (0, 0)))
494 insts
.append((src1
, src2
, dest
, op
, opi
, imm
))
499 def scoreboard_sim(dut
, alusim
):
505 # set random values in the registers
506 for i
in range(1, dut
.n_regs
):
507 val
= randint(0, (1<<alusim
.rwidth
)-1)
510 yield dut
.intregs
.regs
[i
].reg
.eq(val
)
511 alusim
.setval(i
, val
)
513 # create some instructions (some random, some regression tests)
516 instrs
= create_random_ops(dut
, 15, True, 4)
519 instrs
.append( (1, 2, 2, 1, 1, 20, (0, 0)) )
522 instrs
.append( (7, 3, 2, 4, (0, 0)) )
523 instrs
.append( (7, 6, 6, 2, (0, 0)) )
524 instrs
.append( (1, 7, 2, 2, (0, 0)) )
527 instrs
.append((2, 3, 3, 0, 0, 0, (0, 0)))
528 instrs
.append((5, 3, 3, 1, 0, 0, (0, 0)))
529 instrs
.append((3, 5, 5, 2, 0, 0, (0, 0)))
530 instrs
.append((5, 3, 3, 3, 0, 0, (0, 0)))
531 instrs
.append((3, 5, 5, 0, 0, 0, (0, 0)))
534 instrs
.append( (3, 3, 4, 0, 0, 13979, (0, 0)))
535 instrs
.append( (6, 4, 1, 2, 0, 40976, (0, 0)))
536 instrs
.append( (1, 4, 7, 4, 1, 23652, (0, 0)))
539 instrs
.append((5, 6, 2, 1))
540 instrs
.append((2, 2, 4, 0))
541 #instrs.append((2, 2, 3, 1))
544 instrs
.append((2, 1, 2, 3))
547 instrs
.append((2, 6, 2, 1))
548 instrs
.append((2, 1, 2, 0))
551 instrs
.append((1, 2, 7, 2))
552 instrs
.append((7, 1, 5, 0))
553 instrs
.append((4, 4, 1, 1))
556 instrs
.append((5, 6, 2, 2))
557 instrs
.append((1, 1, 4, 1))
558 instrs
.append((6, 5, 3, 0))
561 # Write-after-Write Hazard
562 instrs
.append( (3, 6, 7, 2) )
563 instrs
.append( (4, 4, 7, 1) )
566 # self-read/write-after-write followed by Read-after-Write
567 instrs
.append((1, 1, 1, 1))
568 instrs
.append((1, 5, 3, 0))
571 # Read-after-Write followed by self-read-after-write
572 instrs
.append((5, 6, 1, 2))
573 instrs
.append((1, 1, 1, 1))
576 # self-read-write sandwich
577 instrs
.append((5, 6, 1, 2))
578 instrs
.append((1, 1, 1, 1))
579 instrs
.append((1, 5, 3, 0))
583 instrs
.append( (5, 2, 5, 2) )
584 instrs
.append( (2, 6, 3, 0) )
585 instrs
.append( (4, 2, 2, 1) )
589 yield dut
.intregs
.regs
[5].reg
.eq(v1
)
591 yield dut
.intregs
.regs
[3].reg
.eq(5)
593 instrs
.append((5, 3, 3, 4, (0, 0)))
594 instrs
.append((4, 2, 1, 2, (0, 1)))
598 yield dut
.intregs
.regs
[5].reg
.eq(v1
)
600 yield dut
.intregs
.regs
[3].reg
.eq(5)
602 instrs
.append((5, 3, 3, 4, (0, 0)))
603 instrs
.append((4, 2, 1, 2, (1, 0)))
606 instrs
.append( (4, 3, 5, 1, 0, (0, 0)) )
607 instrs
.append( (5, 2, 3, 1, 0, (0, 0)) )
608 instrs
.append( (7, 1, 5, 2, 0, (0, 0)) )
609 instrs
.append( (5, 6, 6, 4, 0, (0, 0)) )
610 instrs
.append( (7, 5, 2, 2, 0, (1, 0)) )
611 instrs
.append( (1, 7, 5, 0, 0, (0, 1)) )
612 instrs
.append( (1, 6, 1, 2, 0, (1, 0)) )
613 instrs
.append( (1, 6, 7, 3, 0, (0, 0)) )
614 instrs
.append( (6, 7, 7, 0, 0, (0, 0)) )
616 # issue instruction(s), wait for issue to be free before proceeding
617 for i
, instr
in enumerate(instrs
):
618 src1
, src2
, dest
, op
, opi
, imm
, (br_ok
, br_fail
) = instr
620 print ("instr %d: (%d, %d, %d, %d, %d, %d)" % \
621 (i
, src1
, src2
, dest
, op
, opi
, imm
))
622 alusim
.op(op
, opi
, imm
, src1
, src2
, dest
)
623 yield from instr_q(dut
, op
, opi
, imm
, src1
, src2
, dest
,
626 # wait for all instructions to stop before checking
628 iqlen
= yield dut
.qlen_o
636 yield from wait_for_busy_clear(dut
)
639 yield from alusim
.check(dut
)
640 yield from alusim
.dump(dut
)
643 def test_scoreboard():
644 dut
= IssueToScoreboard(2, 1, 1, 16, 8, 8)
645 alusim
= RegSim(16, 8)
646 memsim
= MemSim(16, 16)
647 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
648 with
open("test_scoreboard6600.il", "w") as f
:
651 run_simulation(dut
, scoreboard_sim(dut
, alusim
),
652 vcd_name
='test_scoreboard6600.vcd')
654 #run_simulation(dut, scoreboard_branch_sim(dut, alusim),
655 # vcd_name='test_scoreboard6600.vcd')
659 yield dut
.ld_i
.eq(0x1)
660 yield dut
.fn_issue_i
.eq(0x1)
662 yield dut
.ld_i
.eq(0x0)
663 yield dut
.st_i
.eq(0x3)
664 yield dut
.fn_issue_i
.eq(0x2)
666 yield dut
.st_i
.eq(0x0)
667 yield dut
.fn_issue_i
.eq(0x0)
670 yield dut
.addrs_i
[0].eq(0x012)
671 yield dut
.addrs_i
[1].eq(0x012)
672 yield dut
.addrs_i
[2].eq(0x010)
673 yield dut
.addr_en_i
.eq(0x3)
675 yield dut
.addr_we_i
.eq(0x3)
677 yield dut
.go_ld_i
.eq(0x1)
679 yield dut
.go_ld_i
.eq(0x0)
681 yield dut
.go_st_i
.eq(0x2)
683 yield dut
.go_st_i
.eq(0x0)
688 dut
= MemFunctionUnits(3, 11)
689 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
690 with
open("test_mem_fus.il", "w") as f
:
693 run_simulation(dut
, mem_sim(dut
),
694 vcd_name
='test_mem_fus.vcd')
697 if __name__
== '__main__':