f4667b6ed52634e82aba215a708ef63ec20e177a
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
.asserts
import Assert
14 from nmigen
.cli
import main
, verilog
16 from nmutil
.singlepipe
import PassThroughStage
17 from nmutil
.multipipe
import CombMuxOutPipe
18 from nmutil
.multipipe
import PriorityCombMuxInPipe
22 return int(log(n
) / log(2))
26 def __init__(self
, pspec
):
27 """ creates a pipeline context. currently: operator (op) and muxid
29 opkls (within pspec) - the class to create that will be the
30 "operator". instance must have an "eq"
33 self
.id_wid
= pspec
.id_wid
34 self
.op_wid
= pspec
.op_wid
35 self
.muxid
= Signal(self
.id_wid
, reset_less
=True) # RS multiplex ID
38 self
.op
= Signal(self
.op_wid
, reset_less
=True)
40 self
.op
= opkls(pspec
)
43 ret
= [self
.muxid
.eq(i
.muxid
)]
44 ret
.append(self
.op
.eq(i
.op
))
45 # don't forget to update matches if you add fields later.
48 def matches(self
, another
):
50 Returns a list of Assert()s validating that this context
51 matches the other context.
53 # I couldn't figure a clean way of overloading the == operator.
55 Assert(self
.muxid
== another
.muxid
),
56 Assert(self
.op
== another
.op
),
64 if hasattr(self
.op
, "ports"):
65 return [self
.muxid
] + self
.op
.ports()
70 class InMuxPipe(PriorityCombMuxInPipe
):
71 def __init__(self
, num_rows
, iospecfn
, maskwid
=0):
72 self
.num_rows
= num_rows
73 stage
= PassThroughStage(iospecfn
)
74 PriorityCombMuxInPipe
.__init
__(self
, stage
, p_len
=self
.num_rows
,
78 class MuxOutPipe(CombMuxOutPipe
):
79 def __init__(self
, num_rows
, iospecfn
, maskwid
=0):
80 self
.num_rows
= num_rows
81 stage
= PassThroughStage(iospecfn
)
82 CombMuxOutPipe
.__init
__(self
, stage
, n_len
=self
.num_rows
,
86 class ReservationStations(Elaboratable
):
87 """ Reservation-Station pipeline
89 Input: num_rows - number of input and output Reservation Stations
91 Requires: the addition of an "alu" object, from which ispec and ospec
92 are taken, and inpipe and outpipe are connected to it
94 * fan-in on inputs (an array of BaseData: a,b,mid)
96 * fan-out on outputs (an array of FPPackData: z,mid)
98 Fan-in and Fan-out are combinatorial.
100 def __init__(self
, num_rows
, maskwid
=0, feedback_width
=None):
101 self
.num_rows
= nr
= num_rows
102 self
.feedback_width
= feedback_width
103 self
.inpipe
= InMuxPipe(nr
, self
.i_specfn
, maskwid
) # fan-in
104 self
.outpipe
= MuxOutPipe(nr
, self
.o_specfn
, maskwid
) # fan-out
106 self
.p
= self
.inpipe
.p
# kinda annoying,
107 self
.n
= self
.outpipe
.n
# use pipe in/out as this class in/out
108 self
._ports
= self
.inpipe
.ports() + self
.outpipe
.ports()
110 def elaborate(self
, platform
):
112 m
.submodules
.inpipe
= self
.inpipe
113 m
.submodules
.alu
= self
.alu
114 m
.submodules
.outpipe
= self
.outpipe
116 m
.d
.comb
+= self
.inpipe
.n
.connect_to_next(self
.alu
.p
)
117 m
.d
.comb
+= self
.alu
.connect_to_next(self
.outpipe
)
119 if self
.feedback_width
is None:
122 # connect all outputs above the feedback width back to their inputs
123 # (hence, feedback). pipeline stages are then expected to *modify*
124 # the muxid (with care) in order to use the "upper numbered" RSes
125 # for storing partially-completed results. micro-coding, basically
127 for i
in range(self
.feedback_width
, self
.num_rows
):
128 self
.outpipe
.n
[i
].connect_to_next(self
.inpipe
.p
[i
])
136 return self
.alu
.ispec()
139 return self
.alu
.ospec()