1 """ concurrent unit from mitch alsup augmentations to 6600 scoreboard
4 * data goes through a pipeline
5 * results fan back out.
7 the output data format has to have a member "muxid", which is used
8 as the array index on fan-out
12 from nmigen
import Module
, Elaboratable
, Signal
13 from nmigen
.cli
import main
, verilog
15 from nmutil
.singlepipe
import PassThroughStage
16 from nmutil
.multipipe
import CombMuxOutPipe
17 from nmutil
.multipipe
import PriorityCombMuxInPipe
21 return int(log(n
) / log(2))
25 def __init__(self
, pspec
):
26 """ creates a pipeline context. currently: operator (op) and muxid
28 opkls (within pspec) - the class to create that will be the
29 "operator". instance must have an "eq"
32 self
.id_wid
= pspec
.id_wid
33 self
.op_wid
= pspec
.op_wid
34 self
.muxid
= Signal(self
.id_wid
, reset_less
=True) # RS multiplex ID
37 self
.op
= Signal(self
.op_wid
, reset_less
=True)
39 self
.op
= opkls(pspec
)
42 ret
= [self
.muxid
.eq(i
.muxid
)]
43 ret
.append(self
.op
.eq(i
.op
))
51 if hasattr(self
.op
, "ports"):
52 return [self
.muxid
] + self
.op
.ports()
57 class InMuxPipe(PriorityCombMuxInPipe
):
58 def __init__(self
, num_rows
, iospecfn
, maskwid
=0):
59 self
.num_rows
= num_rows
60 stage
= PassThroughStage(iospecfn
)
61 PriorityCombMuxInPipe
.__init
__(self
, stage
, p_len
=self
.num_rows
,
65 class MuxOutPipe(CombMuxOutPipe
):
66 def __init__(self
, num_rows
, iospecfn
, maskwid
=0):
67 self
.num_rows
= num_rows
68 stage
= PassThroughStage(iospecfn
)
69 CombMuxOutPipe
.__init
__(self
, stage
, n_len
=self
.num_rows
,
73 class ReservationStations(Elaboratable
):
74 """ Reservation-Station pipeline
76 Input: num_rows - number of input and output Reservation Stations
78 Requires: the addition of an "alu" object, from which ispec and ospec
79 are taken, and inpipe and outpipe are connected to it
81 * fan-in on inputs (an array of BaseData: a,b,mid)
83 * fan-out on outputs (an array of FPPackData: z,mid)
85 Fan-in and Fan-out are combinatorial.
87 def __init__(self
, num_rows
, maskwid
=0, feedback_width
=None):
88 self
.num_rows
= nr
= num_rows
89 self
.feedback_width
= feedback_width
90 self
.inpipe
= InMuxPipe(nr
, self
.i_specfn
, maskwid
) # fan-in
91 self
.outpipe
= MuxOutPipe(nr
, self
.o_specfn
, maskwid
) # fan-out
93 self
.p
= self
.inpipe
.p
# kinda annoying,
94 self
.n
= self
.outpipe
.n
# use pipe in/out as this class in/out
95 self
._ports
= self
.inpipe
.ports() + self
.outpipe
.ports()
97 def elaborate(self
, platform
):
99 m
.submodules
.inpipe
= self
.inpipe
100 m
.submodules
.alu
= self
.alu
101 m
.submodules
.outpipe
= self
.outpipe
103 m
.d
.comb
+= self
.inpipe
.n
.connect_to_next(self
.alu
.p
)
104 m
.d
.comb
+= self
.alu
.connect_to_next(self
.outpipe
)
106 if self
.feedback_width
is None:
109 # connect all outputs above the feedback width back to their inputs
110 # (hence, feedback). pipeline stages are then expected to *modify*
111 # the muxid (with care) in order to use the "upper numbered" RSes
112 # for storing partially-completed results. micro-coding, basically
114 for i
in range(self
.feedback_width
, self
.num_rows
):
115 self
.outpipe
.n
[i
].connect_to_next(self
.inpipe
.p
[i
])
123 return self
.alu
.ispec()
126 return self
.alu
.ospec()