from soc.decoder.power_decoder2 import Data
from soc.decoder.power_enums import InternalOp
+from soc.fu.regspec import RegSpec, RegSpecALUAPI
""" Computation Unit (aka "ALU Manager").
return r
# see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
-def get_regspec_bitwidth(regspec, srcdest, idx):
- bitspec = regspec[srcdest][idx]
- wid = 0
- print (bitspec)
- for ranges in bitspec[2].split(","):
- ranges = ranges.split(":")
- print (ranges)
- if len(ranges) == 1: # only one bit
- wid += 1
- else:
- start, end = map(int, ranges)
- wid += (end-start)+1
- return wid
-
-
-class CompUnitRecord(RecordObject):
+
+class CompUnitRecord(RegSpec, RecordObject):
"""CompUnitRecord
base class for Computation Units, to provide a uniform API
see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
"""
def __init__(self, subkls, rwid, n_src=None, n_dst=None, name=None):
+ RegSpec.__init__(self, rwid, n_src, n_dst)
RecordObject.__init__(self, name)
- self._rwid = rwid
- if isinstance(rwid, int):
- # rwid: integer (covers all registers)
- self._n_src, self._n_dst = n_src, n_dst
- else:
- # rwid: a regspec.
- self._n_src, self._n_dst = len(rwid[0]), len(rwid[1])
self._subkls = subkls
+ # create source operands
src = []
for i in range(n_src):
j = i + 1 # name numbering to match src1/src2
src.append(sreg)
self._src_i = src
+ # create dest operands
dst = []
for i in range(n_dst):
j = i + 1 # name numbering to match dest1/2...
dst.append(dreg)
self._dest = dst
+ # operation / data input
+ self.oper_i = subkls() # operand
+
+ # create read/write and other scoreboard signalling
self.rd = go_record(n_src, name="rd") # read in, req out
self.wr = go_record(n_dst, name="wr") # write in, req out
self.issue_i = Signal(reset_less=True) # fn issue in
self.shadown_i = Signal(reset=1) # shadow function, defaults to ON
self.go_die_i = Signal() # go die (reset)
- # operation / data input
- self.oper_i = subkls() # operand
-
# output (busy/done)
self.busy_o = Signal(reset_less=True) # fn busy out
self.done_o = Signal(reset_less=True)
- def _get_dstwid(self, i):
- if isinstance(self._rwid, int):
- return self._rwid
- return get_regspec_bitwidth(self._rwid, 1, i)
-
- def _get_srcwid(self, i):
- if isinstance(self._rwid, int):
- return self._rwid
- return get_regspec_bitwidth(self._rwid, 0, i)
-
-class MultiCompUnit(Elaboratable):
+class MultiCompUnit(RegSpecALUAPI, Elaboratable):
def __init__(self, rwid, alu, opsubsetkls, n_src=2, n_dst=1):
"""MultiCompUnit
* :n_src: number of src operands
* :n_dst: number of destination operands
"""
+ RegSpecALUAPI.__init__(self, rwid, alu)
self.n_src, self.n_dst = n_src, n_dst
- self.rwid = rwid
self.opsubsetkls = opsubsetkls
- self.alu = alu # actual ALU - set as a "submodule" of the CU
self.cu = cu = CompUnitRecord(opsubsetkls, rwid, n_src, n_dst)
+ # convenience names for src operands
for i in range(n_src):
j = i + 1 # name numbering to match src1/src2
name = "src%d_i" % j
setattr(self, name, getattr(cu, name))
+ # convenience names for dest operands
for i in range(n_dst):
j = i + 1 # name numbering to match dest1/2...
name = "dest%d_i" % j
setattr(self, name, getattr(cu, name))
- # convenience names
+ # more convenience names
self.rd = cu.rd
self.wr = cu.wr
self.go_rd_i = self.rd.go # temporary naming
self.data_o = self.dest[0] # Dest out
self.done_o = cu.done_o
- def get_out(self, i):
- if isinstance(self.rwid, int): # old - testing - API (rwid is int)
- return self.alu.out[i]
- # regspec-based API: look up variable through regspec according to row number
- return getattr(self.alu.n.data_o, self.rwid[1][i][1])
-
- def get_in(self, i):
- if isinstance(self.rwid, int): # old - testing - API (rwid is int)
- return self.alu.i[i]
- # regspec-based API: look up variable through regspec according to row number
- return getattr(self.alu.p.data_i, self.rwid[0][i][1])
-
- def get_op(self):
- if isinstance(self.rwid, int): # old - testing - API (rwid is int)
- return self.alu.op
- return self.alu.p.data_i.ctx.op
def elaborate(self, platform):
m = Module()
m.submodules.alu = self.alu