from soc.fu.regspec import RegSpec, RegSpecALUAPI
+def find_ok(fields):
+ """find_ok helper function - finds field ending in "_ok"
+ """
+ for field_name in fields:
+ if field_name.endswith("_ok"):
+ return field_name
+ return None
+
+
def go_record(n, name):
r = Record([('go', n, DIR_FANIN),
('rel', n, DIR_FANOUT)], name=name)
r.rel.reset_less = True
return r
+
# see https://libre-soc.org/3d_gpu/architecture/regfile/ section on regspecs
class CompUnitRecord(RegSpec, RecordObject):
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.rdmaskn = Signal(n_src, reset_less=True) # read mask
+ self.wrmask = Signal(n_dst, reset_less=True) # write mask
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)
self.rd = cu.rd
self.wr = cu.wr
self.rdmaskn = cu.rdmaskn
+ self.wrmask = cu.wrmask
self.go_rd_i = self.rd.go # temporary naming
self.go_wr_i = self.wr.go # temporary naming
self.rd_rel_o = self.rd.rel # temporary naming
ok = Const(1, 1)
if isinstance(lro, Record):
data_r = Record.like(lro, name=name)
- if hasattr(data_r, "ok"): # bye-bye abstract interface design..
- ok = data_r.ok
+ print ("wr fields", i, lro, data_r.fields)
+ # bye-bye abstract interface design..
+ fname = find_ok(data_r.fields)
+ if fname:
+ ok = data_r[fname]
else:
data_r = Signal.like(lro, name=name, reset_less=True)
wrok.append(ok)
# now actually use those to create a write-mask. this basically
# is now the Function Unit API tells the Comp Unit "do not request
# a regfile port because this particular output is not valid"
- wrmask = Signal(self.n_dst, reset_less=True)
- m.d.comb += wrmask.eq(Cat(*wrok))
+ m.d.comb += self.wrmask.eq(Cat(*wrok))
# pass the operation to the ALU
m.d.comb += self.get_op().eq(oper_r)
# write-release gated by busy and by shadow (and write-mask)
brd = Repl(self.busy_o & self.shadown_i, self.n_dst)
- m.d.comb += self.wr.rel.eq(req_l.q & brd & wrmask)
+ m.d.comb += self.wr.rel.eq(req_l.q & brd & self.wrmask)
# output the data from the latch on go_write
for i in range(self.n_dst):
from soc.fu.alu.test.test_pipe_caller import TestCase, ALUTestCase, test_data
from soc.fu.compunits.compunits import ALUFunctionUnit
+from soc.experiment.compalu_multi import find_ok # hack
import random
def set_cu_input(cu, idx, data):
yield cu.rd.go[idx].eq(0)
-def get_cu_output(cu, idx):
+def get_cu_output(cu, idx, code):
+ wrmask = yield cu.wrmask
+ wrop = cu.get_out_name(idx)
+ wrok = cu.get_out(idx)
+ fname = find_ok(wrok.fields)
+ wrok = yield getattr(wrok, fname)
+ print ("wr_rel mask", repr(code), idx, wrop, bin(wrmask), fname, wrok)
+ assert wrmask & (1<<idx), \
+ "get_cu_output '%s': mask bit %d not set\n" \
+ "write-operand '%s' Data.ok likely not set (%s)" \
+ % (code, idx, wrop, hex(wrok))
while True:
wr_relall_o = yield cu.wr.rel
wr_rel_o = yield cu.wr.rel[idx]
yield
rd_rel_o = yield cu.rd.rel
wr_rel_o = yield cu.wr.rel
- print ("after inputs, rd_rel, wr_rel: ",
- bin(rd_rel_o), bin(wr_rel_o))
+ wrmask = yield cu.wrmask
+ print ("after inputs, rd_rel, wr_rel, wrmask: ",
+ bin(rd_rel_o), bin(wr_rel_o), bin(wrmask))
opname = code.split(' ')[0]
yield from sim.call(opname)
index = sim.pc.CIA.value//4
if out_reg_valid:
write_reg_idx = yield pdecode2.e.write_reg.data
expected = sim.gpr(write_reg_idx).value
- cu_out = yield from get_cu_output(cu, 0)
+ cu_out = yield from get_cu_output(cu, 0, code)
print(f"expected {expected:x}, actual: {cu_out:x}")
self.assertEqual(expected, cu_out, code)
yield
wr_rel_o = yield cu.wr.rel[i]
if wr_rel_o:
print ("discard output", i)
- discard = yield from get_cu_output(cu, i)
+ discard = yield from get_cu_output(cu, i, code)
yield
sim.add_sync_process(process)
if rc or \
op == InternalOp.OP_CMP.value or \
op == InternalOp.OP_CMPEQB.value:
- cr_actual = yield from get_cu_output(cu, 1)
+ cr_actual = yield from get_cu_output(cu, 1, code)
if rc:
cr_expected = sim.crl[0].get_range().value
cry_out = yield dec2.e.output_carry
if cry_out:
expected_carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
- xer_ca = yield from get_cu_output(cu, 2)
+ xer_ca = yield from get_cu_output(cu, 2, code)
real_carry = xer_ca & 0b1 # XXX CO not CO32
self.assertEqual(expected_carry, real_carry, code)
expected_carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
real_carry32 = bool(xer_ca & 0b10) # XXX CO32
self.assertEqual(expected_carry32, real_carry32, code)
- xer_ov = yield from get_cu_output(cu, 3)
- xer_so = yield from get_cu_output(cu, 4)
+ xer_ov = yield from get_cu_output(cu, 3, code)
+ xer_so = yield from get_cu_output(cu, 4, code)
if __name__ == "__main__":
self.rwid = rwid
self.alu = alu # actual ALU - set as a "submodule" of the CU
+ def get_in_name(self, i):
+ return self.rwid[0][i][1]
+
+ def get_out_name(self, i):
+ return self.rwid[1][i][1]
+
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 thru row number
- return getattr(self.alu.n.data_o, self.rwid[1][i][1])
+ return getattr(self.alu.n.data_o, self.get_out_name(i))
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 thru row number
- return getattr(self.alu.p.data_i, self.rwid[0][i][1])
+ return getattr(self.alu.p.data_i, self.get_in_name(i))
def get_op(self):
if isinstance(self.rwid, int): # old - testing - API (rwid is int)