whoops trunc_div returning neg/neg result rather than abs/abs
[nmutil.git] / src / nmutil / concurrentunit.py
1 """ concurrent unit from mitch alsup augmentations to 6600 scoreboard
2
3 * data fans in
4 * data goes through a pipeline
5 * results fan back out.
6
7 the output data format has to have a member "muxid", which is used
8 as the array index on fan-out
9 """
10
11 from math import log
12 from nmigen import Module, Elaboratable
13 from nmigen.cli import main, verilog
14
15 from nmutil.singlepipe import PassThroughStage
16 from nmutil.multipipe import CombMuxOutPipe
17 from nmutil.multipipe import PriorityCombMuxInPipe
18
19
20 def num_bits(n):
21 return int(log(n) / log(2))
22
23
24 class InMuxPipe(PriorityCombMuxInPipe):
25 def __init__(self, num_rows, iospecfn, maskwid=0):
26 self.num_rows = num_rows
27 stage = PassThroughStage(iospecfn)
28 PriorityCombMuxInPipe.__init__(self, stage, p_len=self.num_rows,
29 maskwid=maskwid)
30
31
32 class MuxOutPipe(CombMuxOutPipe):
33 def __init__(self, num_rows, iospecfn, maskwid=0):
34 self.num_rows = num_rows
35 stage = PassThroughStage(iospecfn)
36 CombMuxOutPipe.__init__(self, stage, n_len=self.num_rows,
37 maskwid=maskwid)
38
39
40 class ReservationStations(Elaboratable):
41 """ Reservation-Station pipeline
42
43 Input: num_rows - number of input and output Reservation Stations
44
45 Requires: the addition of an "alu" object, from which ispec and ospec
46 are taken, and inpipe and outpipe are connected to it
47
48 * fan-in on inputs (an array of BaseData: a,b,mid)
49 * ALU pipeline
50 * fan-out on outputs (an array of FPPackData: z,mid)
51
52 Fan-in and Fan-out are combinatorial.
53 """
54 def __init__(self, num_rows, maskwid=0, feedback_width=None):
55 self.num_rows = nr = num_rows
56 self.feedback_width = feedback_width
57 self.inpipe = InMuxPipe(nr, self.i_specfn, maskwid) # fan-in
58 self.outpipe = MuxOutPipe(nr, self.o_specfn, maskwid) # fan-out
59
60 self.p = self.inpipe.p # kinda annoying,
61 self.n = self.outpipe.n # use pipe in/out as this class in/out
62 self._ports = self.inpipe.ports() + self.outpipe.ports()
63
64 def elaborate(self, platform):
65 m = Module()
66 m.submodules.inpipe = self.inpipe
67 m.submodules.alu = self.alu
68 m.submodules.outpipe = self.outpipe
69
70 m.d.comb += self.inpipe.n.connect_to_next(self.alu.p)
71 m.d.comb += self.alu.connect_to_next(self.outpipe)
72
73 if self.feedback_width is None:
74 return m
75
76 # connect all outputs above the feedback width back to their inputs
77 # (hence, feedback). pipeline stages are then expected to *modify*
78 # the muxid (with care) in order to use the "upper numbered" RSes
79 # for storing partially-completed results. micro-coding, basically
80
81 for i in range(self.feedback_width, self.num_rows):
82 self.outpipe.n[i].connect_to_next(self.inpipe.p[i])
83
84 return m
85
86 def ports(self):
87 return self._ports
88
89 def i_specfn(self):
90 return self.alu.ispec()
91
92 def o_specfn(self):
93 return self.alu.ospec()