+class CompUnits(Elaboratable):
+
+ def __init__(self, rwid, n_units):
+ """ Inputs:
+
+ * :rwid: bit width of register file(s) - both FP and INT
+ * :n_units: number of ALUs
+
+ Note: bgt unit is returned so that a shadow unit can be created
+ for it
+
+ """
+ self.n_units = n_units
+ self.rwid = rwid
+
+ # inputs
+ self.issue_i = Signal(n_units, reset_less=True)
+ self.go_rd_i = Signal(n_units, reset_less=True)
+ self.go_wr_i = Signal(n_units, reset_less=True)
+ self.shadown_i = Signal(n_units, reset_less=True)
+ self.go_die_i = Signal(n_units, reset_less=True)
+
+ # outputs
+ self.busy_o = Signal(n_units, reset_less=True)
+ self.rd_rel_o = Signal(n_units, reset_less=True)
+ self.req_rel_o = Signal(n_units, reset_less=True)
+
+ # in/out register data (note: not register#, actual data)
+ self.dest_o = Signal(rwid, reset_less=True)
+ self.src1_data_i = Signal(rwid, reset_less=True)
+ self.src2_data_i = Signal(rwid, reset_less=True)
+
+ # Branch ALU and CU
+ self.bgt = BranchALU(self.rwid)
+ self.br1 = ComputationUnitNoDelay(self.rwid, 2, self.bgt)
+
+ def elaborate(self, platform):
+ m = Module()
+
+ # Int ALUs
+ add = ALU(self.rwid)
+ sub = ALU(self.rwid)
+ mul = ALU(self.rwid)
+ shf = ALU(self.rwid)
+ bgt = self.bgt
+
+ m.submodules.comp1 = comp1 = ComputationUnitNoDelay(self.rwid, 2, add)
+ m.submodules.comp2 = comp2 = ComputationUnitNoDelay(self.rwid, 2, sub)
+ m.submodules.comp3 = comp3 = ComputationUnitNoDelay(self.rwid, 2, mul)
+ m.submodules.comp4 = comp4 = ComputationUnitNoDelay(self.rwid, 2, shf)
+ m.submodules.br1 = br1 = self.br1
+ int_alus = [comp1, comp2, comp3, comp4, br1]
+
+ m.d.comb += comp1.oper_i.eq(Const(0, 2)) # op=add
+ m.d.comb += comp2.oper_i.eq(Const(1, 2)) # op=sub
+ m.d.comb += comp3.oper_i.eq(Const(2, 2)) # op=mul
+ m.d.comb += comp4.oper_i.eq(Const(3, 2)) # op=shf
+ m.d.comb += br1.oper_i.eq(Const(0, 2)) # op=bgt
+
+ go_rd_l = []
+ go_wr_l = []
+ issue_l = []
+ busy_l = []
+ req_rel_l = []
+ rd_rel_l = []
+ shadow_l = []
+ godie_l = []
+ for alu in int_alus:
+ req_rel_l.append(alu.req_rel_o)
+ rd_rel_l.append(alu.rd_rel_o)
+ shadow_l.append(alu.shadown_i)
+ godie_l.append(alu.go_die_i)
+ go_wr_l.append(alu.go_wr_i)
+ go_rd_l.append(alu.go_rd_i)
+ issue_l.append(alu.issue_i)
+ busy_l.append(alu.busy_o)
+ m.d.comb += self.rd_rel_o.eq(Cat(*rd_rel_l))
+ m.d.comb += self.req_rel_o.eq(Cat(*req_rel_l))
+ m.d.comb += self.busy_o.eq(Cat(*busy_l))
+ m.d.comb += Cat(*godie_l).eq(self.go_die_i)
+ m.d.comb += Cat(*shadow_l).eq(self.shadown_i)
+ m.d.comb += Cat(*go_wr_l).eq(self.go_wr_i)
+ m.d.comb += Cat(*go_rd_l).eq(self.go_rd_i)
+ m.d.comb += Cat(*issue_l).eq(self.issue_i)
+
+ # connect data register input/output
+
+ # merge (OR) all integer FU / ALU outputs to a single value
+ # bit of a hack: treereduce needs a list with an item named "dest_o"
+ dest_o = treereduce(int_alus)
+ m.d.comb += self.dest_o.eq(dest_o)
+
+ for i, alu in enumerate(int_alus):
+ m.d.comb += alu.src1_i.eq(self.src1_data_i)
+ m.d.comb += alu.src2_i.eq(self.src2_data_i)
+
+ return m
+
+
+class FunctionUnits(Elaboratable):
+
+ def __init__(self, n_regs, n_int_alus):
+ self.n_regs = n_regs
+ self.n_int_alus = n_int_alus
+
+ self.dest_i = Signal(n_regs, reset_less=True) # Dest R# in
+ self.src1_i = Signal(n_regs, reset_less=True) # oper1 R# in
+ self.src2_i = Signal(n_regs, reset_less=True) # oper2 R# in
+
+ self.g_int_rd_pend_o = Signal(n_regs, reset_less=True)
+ self.g_int_wr_pend_o = Signal(n_regs, reset_less=True)
+
+ self.dest_rsel_o = Signal(n_regs, reset_less=True) # dest reg (bot)
+ self.src1_rsel_o = Signal(n_regs, reset_less=True) # src1 reg (bot)
+ self.src2_rsel_o = Signal(n_regs, reset_less=True) # src2 reg (bot)
+
+ self.req_rel_i = Signal(n_int_alus, reset_less = True)
+ self.readable_o = Signal(n_int_alus, reset_less=True)
+ self.writable_o = Signal(n_int_alus, reset_less=True)
+
+ self.go_rd_i = Signal(n_int_alus, reset_less=True)
+ self.go_wr_i = Signal(n_int_alus, reset_less=True)
+ self.req_rel_o = Signal(n_int_alus, reset_less=True)
+ self.fn_issue_i = Signal(n_int_alus, reset_less=True)
+
+ # Note: FURegs wr_pend_o is also outputted from here, for use in WaWGrid
+
+ def elaborate(self, platform):
+ m = Module()
+
+ n_int_fus = self.n_int_alus
+
+ # Integer FU-FU Dep Matrix
+ intfudeps = FUFUDepMatrix(n_int_fus, n_int_fus)
+ m.submodules.intfudeps = intfudeps
+ # Integer FU-Reg Dep Matrix
+ intregdeps = FURegDepMatrix(n_int_fus, self.n_regs)
+ m.submodules.intregdeps = intregdeps
+
+ m.d.comb += self.g_int_rd_pend_o.eq(intregdeps.rd_rsel_o)
+ m.d.comb += self.g_int_wr_pend_o.eq(intregdeps.wr_rsel_o)
+
+ m.d.comb += intregdeps.rd_pend_i.eq(intregdeps.rd_rsel_o)
+ m.d.comb += intregdeps.wr_pend_i.eq(intregdeps.wr_rsel_o)
+
+ m.d.comb += intfudeps.rd_pend_i.eq(intregdeps.rd_pend_o)
+ m.d.comb += intfudeps.wr_pend_i.eq(intregdeps.wr_pend_o)
+ self.wr_pend_o = intregdeps.wr_pend_o # also output for use in WaWGrid
+
+ m.d.comb += intfudeps.issue_i.eq(self.fn_issue_i)
+ m.d.comb += intfudeps.go_rd_i.eq(self.go_rd_i)
+ m.d.comb += intfudeps.go_wr_i.eq(self.go_wr_i)
+ m.d.comb += self.readable_o.eq(intfudeps.readable_o)
+ m.d.comb += self.writable_o.eq(intfudeps.writable_o)
+
+ # Connect function issue / arrays, and dest/src1/src2
+ m.d.comb += intregdeps.dest_i.eq(self.dest_i)
+ m.d.comb += intregdeps.src1_i.eq(self.src1_i)
+ m.d.comb += intregdeps.src2_i.eq(self.src2_i)
+
+ m.d.comb += intregdeps.go_rd_i.eq(self.go_rd_i)
+ m.d.comb += intregdeps.go_wr_i.eq(self.go_wr_i)
+ m.d.comb += intregdeps.issue_i.eq(self.fn_issue_i)
+
+ m.d.comb += self.dest_rsel_o.eq(intregdeps.dest_rsel_o)
+ m.d.comb += self.src1_rsel_o.eq(intregdeps.src1_rsel_o)
+ m.d.comb += self.src2_rsel_o.eq(intregdeps.src2_rsel_o)
+
+ return m
+
+