Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / fu / regspec.py
1 """RegSpecs
2
3 see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
4
5 this module is a key strategic module that links pipeline specifications
6 (soc.fu.*.pipe_data and soc.fo.*.pipeline) to MultiCompUnits. MultiCompUnits
7 know absolutely nothing about the data passing through them: all they know
8 is: how many inputs they need to manage, and how many outputs.
9
10 regspecs tell MultiCompUnit what the ordering of the inputs is, how many to
11 create, and how to connect them up to the ALU being "managed" by this CompUnit.
12 likewise for outputs.
13
14 later (TODO) the Register Files will be connected to MultiCompUnits, and,
15 again, the regspecs will say which Regfile (which type) is connected to
16 which MultiCompUnit port, how wide the connection is, and so on.
17
18 """
19 from nmigen import Const
20 from soc.regfile.regfiles import XERRegs, FastRegs
21
22
23 def get_regspec_bitwidth(regspec, srcdest, idx):
24 print("get_regspec_bitwidth", regspec, srcdest, idx)
25 bitspec = regspec[srcdest][idx]
26 wid = 0
27 print(bitspec)
28 for ranges in bitspec[2].split(","):
29 ranges = ranges.split(":")
30 print(ranges)
31 if len(ranges) == 1: # only one bit
32 wid += 1
33 else:
34 start, end = map(int, ranges)
35 wid += (end-start)+1
36 return wid
37
38
39 class RegSpec:
40 def __init__(self, rwid, n_src=None, n_dst=None, name=None):
41 self._rwid = rwid
42 print ("RegSpec", rwid)
43 if isinstance(rwid, int):
44 # rwid: integer (covers all registers)
45 self._n_src, self._n_dst = n_src, n_dst
46 else:
47 # rwid: a regspec.
48 self._n_src, self._n_dst = len(rwid[0]), len(rwid[1])
49
50 def _get_dstwid(self, i):
51 if isinstance(self._rwid, int):
52 return self._rwid
53 return get_regspec_bitwidth(self._rwid, 1, i)
54
55 def _get_srcwid(self, i):
56 if isinstance(self._rwid, int):
57 return self._rwid
58 return get_regspec_bitwidth(self._rwid, 0, i)
59
60
61 class RegSpecAPI:
62 def __init__(self, rwid):
63 """RegSpecAPI
64
65 * :rwid: regspec
66 """
67 self.rwid = rwid
68
69 def get_io_spec(self, direction, i):
70 if direction: # input (read specs)
71 return self.get_in_spec(i)
72 return self.get_out_spec(i)
73
74 def get_in_spec(self, i):
75 return self.rwid[0][i]
76
77 def get_out_spec(self, i):
78 return self.rwid[1][i]
79
80 def get_in_name(self, i):
81 return self.get_in_spec(i)[1]
82
83 def get_out_name(self, i):
84 return self.get_out_spec(i)[1]
85
86
87 class RegSpecALUAPI(RegSpecAPI):
88 def __init__(self, rwid, alu):
89 """RegSpecAPI
90
91 * :rwid: regspec
92 * :alu: ALU covered by this regspec
93 """
94 super().__init__(rwid)
95 self.alu = alu
96
97 def get_out(self, i):
98 if isinstance(self.rwid, int): # old - testing - API (rwid is int)
99 return self.alu.out[i]
100 # regspec-based API: look up variable through regspec thru row number
101 return getattr(self.alu.n.o_data, self.get_out_name(i))
102
103 def get_in(self, i):
104 if isinstance(self.rwid, int): # old - testing - API (rwid is int)
105 return self.alu.i[i]
106 # regspec-based API: look up variable through regspec thru row number
107 return getattr(self.alu.p.i_data, self.get_in_name(i))
108
109 def get_op(self):
110 if isinstance(self.rwid, int): # old - testing - API (rwid is int)
111 return self.alu.op
112 return self.alu.p.i_data.ctx.op