+# SPDX-License-Identifier: LGPL-3-or-later
""" concurrent unit from mitch alsup augmentations to 6600 scoreboard
This work is funded through NLnet under Grant 2019-02-012
sandwiched in between the fan-in and fan-out. One ALU looks like
it is multiple concurrent ALUs
"""
+
def __init__(self, alu, p, n):
self.alu = alu
self.p = p
Fan-in and Fan-out are combinatorial.
"""
+
def __init__(self, num_rows, maskwid=0, feedback_width=None):
self.num_rows = nr = num_rows
self.feedback_width = feedback_width
self.inpipe = InMuxPipe(nr, self.i_specfn, maskwid) # fan-in
- self.outpipe = MuxOutPipe(nr, self.o_specfn, maskwid) # fan-out
+ self.outpipe = MuxOutPipe(nr, self.o_specfn, maskwid) # fan-out
self.p = self.inpipe.p # kinda annoying,
- self.n = self.outpipe.n # use pipe in/out as this class in/out
+ self.n = self.outpipe.n # use pipe in/out as this class in/out
self._ports = self.inpipe.ports() + self.outpipe.ports()
def setup_pseudoalus(self):
class to correctly set that muxid in each data packet to the
correct constant. this could change in future.
+ FAILING TO SET THE MUXID IS GUARANTEED TO RESULT IN CORRUPTED DATA.
"""
+
def __init__(self, alu, num_rows, alu_name=None):
if alu_name is None:
alu_name = "alu"
self.p.append(p)
self.n.append(n)
- self.pipe = self # for Arbiter to select the incoming prevcontrols
+ self.pipe = self # for Arbiter to select the incoming prevcontrols
# set up pseudo-alus that look like a standard pipeline
self.pseudoalus = []
def elaborate(self, platform):
m = Module()
- pe = PriorityEncoder(self.num_rows) # input priority picker
+ pe = PriorityEncoder(self.num_rows) # input priority picker
m.submodules[self.alu_name] = self.alu
m.submodules.selector = pe
for i, (p, n) in enumerate(zip(self.p, self.n)):
self.m_id = Signal.like(pe.o)
# ReservationStation status information, progressively updated in FSM
- rsvd = Signal(self.num_rows) # indicates RS data in flight
- sent = Signal(self.num_rows) # sent indicates data in pipeline
- wait = Signal(self.num_rows) # the outputs are waiting for accept
+ rsvd = Signal(self.num_rows) # indicates RS data in flight
+ sent = Signal(self.num_rows) # sent indicates data in pipeline
+ wait = Signal(self.num_rows) # the outputs are waiting for accept
# pick first non-reserved ReservationStation with data not already
# sent into the ALU
# mux in and mux out ids. note that all data *must* have a muxid
mid = self.m_id # input mux selector
- o_muxid = self.alu.n.o_data.muxid # output mux selector
+ o_muxid = self.alu.n.o_data.muxid # output mux selector
# technically speaking this could be set permanently "HI".
# when all the ReservationStations outputs are waiting,
# first, establish input: select one input to pass data to (p_mux)
for i in range(self.num_rows):
- i_buf, o_buf = self.alu.new_specs("buf%d" % i) # buffers
+ i_buf, o_buf = self.alu.new_specs("buf%d" % i) # buffers
with m.FSM():
# indicate ready to accept data, and accept it if incoming
# BUT, if there is an opportunity to send on immediately
# to the ALU, take it early (combinatorial)
with m.State("ACCEPTING%d" % i):
- m.d.comb += self.p[i].o_ready.eq(1) # ready indicator
+ m.d.comb += self.p[i].o_ready.eq(1) # ready indicator
with m.If(self.p[i].i_valid): # valid data incoming
m.d.sync += rsvd[i].eq(1) # now reserved
# a unique opportunity: the ALU happens to be free
- with m.If(mid == i): # picker selected us
+ with m.If(mid == i): # picker selected us
with m.If(self.alu.p.o_ready): # ALU can accept
- m.d.comb += self.alu.p.i_valid.eq(1) # transfer
+ # transfer
+ m.d.comb += self.alu.p.i_valid.eq(1)
m.d.comb += nmoperator.eq(self.alu.p.i_data,
- self.p[i].i_data)
- m.d.sync += sent[i].eq(1) # now reserved
- m.next = "WAITOUT%d" % i # move to "wait output"
+ self.p[i].i_data)
+ m.d.sync += sent[i].eq(1) # now reserved
+ m.next = "WAITOUT%d" % i # move to "wait output"
with m.Else():
# nope. ALU wasn't free. try next cycle(s)
m.d.sync += nmoperator.eq(i_buf, self.p[i].i_data)
- m.next = "ACCEPTED%d" % i # move to "accepted"
+ m.next = "ACCEPTED%d" % i # move to "accepted"
# now try to deliver to the ALU, but only if we are "picked"
with m.State("ACCEPTED%d" % i):
- with m.If(mid == i): # picker selected us
+ with m.If(mid == i): # picker selected us
with m.If(self.alu.p.o_ready): # ALU can accept
- m.d.comb += self.alu.p.i_valid.eq(1) # transfer
+ m.d.comb += self.alu.p.i_valid.eq(1) # transfer
m.d.comb += nmoperator.eq(self.alu.p.i_data, i_buf)
- m.d.sync += sent[i].eq(1) # now reserved
- m.next = "WAITOUT%d" % i # move to "wait output"
+ m.d.sync += sent[i].eq(1) # now reserved
+ m.next = "WAITOUT%d" % i # move to "wait output"
# waiting for output to appear on the ALU, take a copy
# BUT, again, if there is an opportunity to send on
# immediately, take it (combinatorial)
with m.State("WAITOUT%d" % i):
- with m.If(o_muxid == i): # when ALU output matches our RS
+ with m.If(o_muxid == i): # when ALU output matches our RS
with m.If(self.alu.n.o_valid): # ALU can accept
# second unique opportunity: the RS is ready
- with m.If(self.n[i].i_ready): # ready to receive
- m.d.comb += self.n[i].o_valid.eq(1) # valid
+ with m.If(self.n[i].i_ready): # ready to receive
+ m.d.comb += self.n[i].o_valid.eq(1) # valid
m.d.comb += nmoperator.eq(self.n[i].o_data,
self.alu.n.o_data)
- m.d.sync += wait[i].eq(0) # clear waiting
- m.d.sync += sent[i].eq(0) # and sending
- m.d.sync += rsvd[i].eq(0) # and reserved
- m.next = "ACCEPTING%d" % i # back to "accepting"
+ m.d.sync += wait[i].eq(0) # clear waiting
+ m.d.sync += sent[i].eq(0) # and sending
+ m.d.sync += rsvd[i].eq(0) # and reserved
+ m.next = "ACCEPTING%d" % i # back to "accepting"
with m.Else():
# nope. RS wasn't ready. try next cycles
- m.d.sync += wait[i].eq(1) # now waiting
+ m.d.sync += wait[i].eq(1) # now waiting
m.d.sync += nmoperator.eq(o_buf,
self.alu.n.o_data)
- m.next = "SENDON%d" % i # move to "send data on"
+ m.next = "SENDON%d" % i # move to "send data on"
# waiting for "valid" indicator on RS output: deliver it
with m.State("SENDON%d" % i):
- with m.If(self.n[i].i_ready): # user is ready to receive
- m.d.comb += self.n[i].o_valid.eq(1) # indicate valid
+ with m.If(self.n[i].i_ready): # user is ready to receive
+ m.d.comb += self.n[i].o_valid.eq(1) # indicate valid
m.d.comb += nmoperator.eq(self.n[i].o_data, o_buf)
- m.d.sync += wait[i].eq(0) # clear waiting
- m.d.sync += sent[i].eq(0) # and sending
- m.d.sync += rsvd[i].eq(0) # and reserved
- m.next = "ACCEPTING%d" % i # and back to "accepting"
+ m.d.sync += wait[i].eq(0) # clear waiting
+ m.d.sync += sent[i].eq(0) # and sending
+ m.d.sync += rsvd[i].eq(0) # and reserved
+ m.next = "ACCEPTING%d" % i # and back to "accepting"
return m
-