m.d.comb += self.o.eq(self.a >> btrunc)
return m
+class Dummy:
+ pass
class ALU(Elaboratable):
def __init__(self, width):
- self.p_valid_i = Signal()
- self.p_ready_o = Signal()
- self.n_ready_i = Signal()
- self.n_valid_o = Signal()
+ self.p = Dummy() # make look like nmutil pipeline API
+ self.n = Dummy() # make look like nmutil pipeline API
+ self.p.valid_i = Signal()
+ self.p.ready_o = Signal()
+ self.n.ready_i = Signal()
+ self.n.valid_o = Signal()
self.counter = Signal(4)
self.op = CompALUOpSubset()
i = []
go_now = Signal(reset_less=True) # testing no-delay ALU
- with m.If(self.p_valid_i):
+ with m.If(self.p.valid_i):
# input is valid. next check, if we already said "ready" or not
- with m.If(~self.p_ready_o):
+ with m.If(~self.p.ready_o):
# we didn't say "ready" yet, so say so and initialise
- m.d.sync += self.p_ready_o.eq(1)
+ m.d.sync += self.p.ready_o.eq(1)
# as this is a "fake" pipeline, just grab the output right now
with m.If(self.op.insn_type == InternalOp.OP_ADD):
with m.Else():
# input says no longer valid, so drop ready as well.
# a "proper" ALU would have had to sync in the opcode and a/b ops
- m.d.sync += self.p_ready_o.eq(0)
+ m.d.sync += self.p.ready_o.eq(0)
# ok so the counter's running: when it gets to 1, fire the output
with m.If((self.counter == 1) | go_now):
# set the output as valid if the recipient is ready for it
- m.d.sync += self.n_valid_o.eq(1)
- with m.If(self.n_ready_i & self.n_valid_o):
- m.d.sync += self.n_valid_o.eq(0)
+ m.d.sync += self.n.valid_o.eq(1)
+ with m.If(self.n.ready_i & self.n.valid_o):
+ m.d.sync += self.n.valid_o.eq(0)
# recipient said it was ready: reset back to known-good.
m.d.sync += self.counter.eq(0) # reset the counter
m.d.sync += self.o.eq(0) # clear the output for tidiness sake
class BranchALU(Elaboratable):
def __init__(self, width):
- self.p_valid_i = Signal()
- self.p_ready_o = Signal()
- self.n_ready_i = Signal()
- self.n_valid_o = Signal()
+ self.p.valid_i = Signal()
+ self.p.ready_o = Signal()
+ self.n.ready_i = Signal()
+ self.n.valid_o = Signal()
self.counter = Signal(4)
self.op = Signal(2)
i = []
]
go_now = Signal(reset_less=True) # testing no-delay ALU
- with m.If(self.p_valid_i):
+ with m.If(self.p.valid_i):
# input is valid. next check, if we already said "ready" or not
- with m.If(~self.p_ready_o):
+ with m.If(~self.p.ready_o):
# we didn't say "ready" yet, so say so and initialise
- m.d.sync += self.p_ready_o.eq(1)
+ m.d.sync += self.p.ready_o.eq(1)
# as this is a "fake" pipeline, just grab the output right now
with m.Switch(self.op):
with m.Else():
# input says no longer valid, so drop ready as well.
# a "proper" ALU would have had to sync in the opcode and a/b ops
- m.d.sync += self.p_ready_o.eq(0)
+ m.d.sync += self.p.ready_o.eq(0)
# ok so the counter's running: when it gets to 1, fire the output
with m.If((self.counter == 1) | go_now):
# set the output as valid if the recipient is ready for it
- m.d.sync += self.n_valid_o.eq(1)
- with m.If(self.n_ready_i & self.n_valid_o):
- m.d.sync += self.n_valid_o.eq(0)
+ m.d.sync += self.n.valid_o.eq(1)
+ with m.If(self.n.ready_i & self.n.valid_o):
+ m.d.sync += self.n.valid_o.eq(0)
# recipient said it was ready: reset back to known-good.
m.d.sync += self.counter.eq(0) # reset the counter
m.d.sync += self.o.eq(0) # clear the output for tidiness sake
yield dut.b.eq(b)
yield dut.op.insn_type.eq(op)
yield dut.op.invert_a.eq(inv_a)
- yield dut.n_ready_i.eq(0)
- yield dut.p_valid_i.eq(1)
+ yield dut.n.ready_i.eq(0)
+ yield dut.p.valid_i.eq(1)
yield
while True:
yield
- n_valid_o = yield dut.n_valid_o
- if n_valid_o:
+ n.valid_o = yield dut.n.valid_o
+ if n.valid_o:
break
yield
result = yield dut.o
- yield dut.p_valid_i.eq(0)
- yield dut.n_ready_i.eq(0)
+ yield dut.p.valid_i.eq(0)
+ yield dut.n.ready_i.eq(0)
yield
return result
# read-done,wr-proceed latch
m.d.comb += rok_l.s.eq(self.issue_i) # set up when issue starts
- m.d.comb += rok_l.r.eq(self.alu.p_ready_o) # off when ALU acknowledges
+ m.d.comb += rok_l.r.eq(self.alu.p.ready_o) # off when ALU acknowledges
# wr-done, back-to-start latch
m.d.comb += rst_l.s.eq(all_rd) # set when read-phase is fully done
# opcode latch (not using go_rd_i) - inverted so that busy resets to 0
m.d.sync += opc_l.s.eq(self.issue_i) # set on issue
- m.d.sync += opc_l.r.eq(self.alu.n_valid_o & req_done) # reset on ALU
+ m.d.sync += opc_l.r.eq(self.alu.n.valid_o & req_done) # reset on ALU
# src operand latch (not using go_wr_i)
m.d.sync += src_l.s.eq(Repl(self.issue_i, self.n_src))
# NOTE: this spells TROUBLE if the ALU isn't ready!
# go_read is only valid for one clock!
with m.If(all_rd): # src operands ready, GO!
- with m.If(~self.alu.p_ready_o): # no ACK yet
- m.d.comb += self.alu.p_valid_i.eq(1) # so indicate valid
+ with m.If(~self.alu.p.ready_o): # no ACK yet
+ m.d.comb += self.alu.p.valid_i.eq(1) # so indicate valid
brd = Repl(self.busy_o & self.shadown_i, self.n_dst)
# only proceed if ALU says its output is valid
- with m.If(self.alu.n_valid_o):
+ with m.If(self.alu.n.valid_o):
# when ALU ready, write req release out. waits for shadow
m.d.comb += self.wr.rel.eq(req_l.q & brd)
# when output latch is ready, and ALU says ready, accept ALU output
with m.If(reset):
- m.d.comb += self.alu.n_ready_i.eq(1) # tells ALU "thanks got it"
+ m.d.comb += self.alu.n.ready_i.eq(1) # tells ALU "thanks got it"
# output the data from the latch on go_write
for i in range(self.n_dst):