From 943a10d56aa05f6888d39c668074f886a6736bd1 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sat, 23 May 2020 18:08:08 +0100 Subject: [PATCH] make demo/test ALU look like nmigen pipeline API --- src/soc/experiment/alu_hier.py | 60 +++++++++++++++-------------- src/soc/experiment/compalu_multi.py | 12 +++--- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/soc/experiment/alu_hier.py b/src/soc/experiment/alu_hier.py index 72de4874..af373ca3 100644 --- a/src/soc/experiment/alu_hier.py +++ b/src/soc/experiment/alu_hier.py @@ -78,13 +78,17 @@ class Shifter(Elaboratable): 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 = [] @@ -118,11 +122,11 @@ class ALU(Elaboratable): 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): @@ -152,14 +156,14 @@ class ALU(Elaboratable): 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 @@ -195,10 +199,10 @@ class BranchOp(Elaboratable): 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 = [] @@ -228,11 +232,11 @@ class BranchALU(Elaboratable): ] 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): @@ -244,14 +248,14 @@ class BranchALU(Elaboratable): 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 @@ -276,19 +280,19 @@ def run_op(dut, a, b, op, inv_a=0): 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 diff --git a/src/soc/experiment/compalu_multi.py b/src/soc/experiment/compalu_multi.py index b25749c8..7cdd19d0 100644 --- a/src/soc/experiment/compalu_multi.py +++ b/src/soc/experiment/compalu_multi.py @@ -235,7 +235,7 @@ class MultiCompUnit(Elaboratable): # 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 @@ -243,7 +243,7 @@ class MultiCompUnit(Elaboratable): # 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)) @@ -318,17 +318,17 @@ class MultiCompUnit(Elaboratable): # 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): -- 2.30.2