+# dictionary of Input Record field names that, if they exist,
+# will need a corresponding CSV Decoder file column (actually, PowerOp)
+# to be decoded (this includes the single bit names)
+record_names = {'insn_type': 'internal_op',
+ 'fn_unit': 'function_unit',
+ 'rc': 'rc_sel',
+ 'oe': 'rc_sel',
+ 'zero_a': 'in1_sel',
+ 'imm_data': 'in2_sel',
+ 'invert_in': 'inv_a',
+ 'invert_out': 'inv_out',
+ 'rc': 'cr_out',
+ 'oe': 'cr_in',
+ 'output_carry': 'cry_out',
+ 'input_carry': 'cry_in',
+ 'is_32bit': 'is_32b',
+ 'is_signed': 'sgn',
+ 'lk': 'lk',
+ 'data_len': 'ldst_len',
+ 'byte_reverse': 'br',
+ 'sign_extend': 'sgn_ext',
+ 'ldst_mode': 'upd',
+ }
+
+
+class PowerDecodeSubset(Elaboratable):
+ """PowerDecodeSubset: dynamic subset decoder
+
+ only fields actually requested are copied over. hence, "subset" (duh).
+ """
+ def __init__(self, dec, opkls=None, fn_name=None, final=False, state=None):
+
+ self.sv_rm = SVP64Rec(name="dec_svp64") # SVP64 RM field
+ self.final = final
+ self.opkls = opkls
+ self.fn_name = fn_name
+ if opkls is None:
+ opkls = Decode2ToOperand
+ self.do = opkls(fn_name)
+ col_subset = self.get_col_subset(self.do)
+
+ # only needed for "main" PowerDecode2
+ if not self.final:
+ self.e = Decode2ToExecute1Type(name=self.fn_name, do=self.do)
+
+ # create decoder if one not already given
+ if dec is None:
+ dec = create_pdecode(name=fn_name, col_subset=col_subset,
+ row_subset=self.rowsubsetfn)
+ self.dec = dec
+
+ # state information needed by the Decoder
+ if state is None:
+ state = CoreState("dec2")
+ self.state = state
+
+ def get_col_subset(self, do):
+ subset = {'sv_cr_in', 'sv_cr_out', 'SV_Etype',
+ 'cr_in', 'cr_out', 'rc_sel'} # needed, non-optional
+ for k, v in record_names.items():
+ if hasattr(do, k):
+ subset.add(v)
+ print ("get_col_subset", self.fn_name, do.fields, subset)
+ return subset
+
+ def rowsubsetfn(self, opcode, row):
+ return row['unit'] == self.fn_name
+
+ def ports(self):
+ return self.dec.ports() + self.e.ports() + self.sv_rm.ports()
+
+ def needs_field(self, field, op_field):
+ if self.final:
+ do = self.do
+ else:
+ do = self.e_tmp.do
+ return hasattr(do, field) and self.op_get(op_field) is not None
+
+ def do_copy(self, field, val, final=False):
+ if final or self.final:
+ do = self.do
+ else:
+ do = self.e_tmp.do
+ if hasattr(do, field) and val is not None:
+ return getattr(do, field).eq(val)
+ return []
+
+ def op_get(self, op_field):
+ return getattr(self.dec.op, op_field, None)
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+ state = self.state
+ op, do = self.dec.op, self.do
+ msr, cia = state.msr, state.pc
+
+ # fill in for a normal instruction (not an exception)
+ # copy over if non-exception, non-privileged etc. is detected
+ if not self.final:
+ if self.fn_name is None:
+ name = "tmp"
+ else:
+ name = self.fn_name + "tmp"
+ self.e_tmp = Decode2ToExecute1Type(name=name, opkls=self.opkls)
+
+ # set up submodule decoders
+ m.submodules.dec = self.dec
+ m.submodules.dec_rc = dec_rc = DecodeRC(self.dec)
+ m.submodules.dec_oe = dec_oe = DecodeOE(self.dec)
+ m.submodules.dec_cr_in = self.dec_cr_in = DecodeCRIn(self.dec)
+ m.submodules.dec_cr_out = self.dec_cr_out = DecodeCROut(self.dec)
+
+ # copy instruction through...
+ for i in [do.insn,
+ dec_rc.insn_in, dec_oe.insn_in,
+ self.dec_cr_in.insn_in, self.dec_cr_out.insn_in]:
+ comb += i.eq(self.dec.opcode_in)
+
+ # ...and subdecoders' input fields
+ comb += dec_rc.sel_in.eq(op.rc_sel)
+ comb += dec_oe.sel_in.eq(op.rc_sel) # XXX should be OE sel
+ comb += self.dec_cr_in.sel_in.eq(op.cr_in)
+ comb += self.dec_cr_in.sv_rm.eq(self.sv_rm)
+ comb += self.dec_cr_out.sv_rm.eq(self.sv_rm)
+ comb += self.dec_cr_out.sel_in.eq(op.cr_out)
+ comb += self.dec_cr_out.rc_in.eq(dec_rc.rc_out.data)
+
+ # copy "state" over
+ comb += self.do_copy("msr", msr)
+ comb += self.do_copy("cia", cia)
+
+ # set up instruction type
+ # no op: defaults to OP_ILLEGAL
+ comb += self.do_copy("insn_type", self.op_get("internal_op"))
+
+ # function unit for decoded instruction: requires minor redirect
+ # for SPR set/get
+ fn = self.op_get("function_unit")
+ spr = Signal(10, reset_less=True)
+ comb += spr.eq(decode_spr_num(self.dec.SPR)) # from XFX
+
+ # for first test only forward SPRs 18 and 19 to MMU, when
+ # operation is MTSPR or MFSPR. TODO: add other MMU SPRs
+ with m.If(((self.dec.op.internal_op == MicrOp.OP_MTSPR) |
+ (self.dec.op.internal_op == MicrOp.OP_MFSPR)) &
+ ((spr == SPR.DSISR) | (spr == SPR.DAR))):
+ comb += self.do_copy("fn_unit", Function.MMU)
+ with m.Else():
+ comb += self.do_copy("fn_unit",fn)
+
+ # immediates
+ if self.needs_field("zero_a", "in1_sel"):
+ m.submodules.dec_ai = dec_ai = DecodeAImm(self.dec)
+ comb += dec_ai.sel_in.eq(op.in1_sel)
+ comb += self.do_copy("zero_a", dec_ai.immz_out) # RA==0 detected
+ if self.needs_field("imm_data", "in2_sel"):
+ m.submodules.dec_bi = dec_bi = DecodeBImm(self.dec)
+ comb += dec_bi.sel_in.eq(op.in2_sel)
+ comb += self.do_copy("imm_data", dec_bi.imm_out) # imm in RB
+
+ # rc and oe out
+ comb += self.do_copy("rc", dec_rc.rc_out)
+ comb += self.do_copy("oe", dec_oe.oe_out)
+
+ # CR in/out
+ comb += self.do_copy("read_cr_whole", self.dec_cr_in.whole_reg)
+ comb += self.do_copy("write_cr_whole", self.dec_cr_out.whole_reg)
+ comb += self.do_copy("write_cr0", self.dec_cr_out.cr_bitfield.ok)
+
+ comb += self.do_copy("input_cr", self.op_get("cr_in")) # CR in
+ comb += self.do_copy("output_cr", self.op_get("cr_out")) # CR out
+
+ # decoded/selected instruction flags
+ comb += self.do_copy("data_len", self.op_get("ldst_len"))
+ comb += self.do_copy("invert_in", self.op_get("inv_a"))
+ comb += self.do_copy("invert_out", self.op_get("inv_out"))
+ comb += self.do_copy("input_carry", self.op_get("cry_in"))
+ comb += self.do_copy("output_carry", self.op_get("cry_out"))
+ comb += self.do_copy("is_32bit", self.op_get("is_32b"))
+ comb += self.do_copy("is_signed", self.op_get("sgn"))
+ lk = self.op_get("lk")
+ if lk is not None:
+ with m.If(lk):
+ comb += self.do_copy("lk", self.dec.LK) # XXX TODO: accessor
+
+ comb += self.do_copy("byte_reverse", self.op_get("br"))
+ comb += self.do_copy("sign_extend", self.op_get("sgn_ext"))
+ comb += self.do_copy("ldst_mode", self.op_get("upd")) # LD/ST mode
+
+ return m
+