import gc
from collections import namedtuple, OrderedDict
-from nmigen import Module, Elaboratable, Signal, Cat, Mux
-from nmigen.cli import rtlil
+from nmigen import Module, Elaboratable, Signal, Cat, Mux, Const
+from nmigen.cli import rtlil, verilog
from openpower.decoder.power_enums import (Function, Form, MicrOp,
In1Sel, In2Sel, In3Sel, OutSel,
SVEXTRA, SVEtype, SVPtype, # Simple-V
RC, LdstLen, LDSTMode, CryIn,
single_bit_flags, CRInSel,
CROutSel, get_signal_name,
- default_values, insns, asmidx)
+ default_values, insns, asmidx,
+ asmlen)
from openpower.decoder.power_fields import DecodeFields
from openpower.decoder.power_fieldsn import SigDecode, SignalBitRange
from openpower.decoder.power_svp64 import SVP64RM
power_op_types = {'function_unit': Function,
'internal_op': MicrOp,
'form': Form,
- 'asmcode': 8,
+ 'asmcode': asmlen,
'SV_Etype': SVEtype,
'SV_Ptype': SVPtype,
'in1_sel': In1Sel,
row_subset=None, conditions=None):
if conditions is None:
# XXX conditions = {}
- conditions = {'SVP64BREV': 0,
- '~SVP64BREV': 1,
+ conditions = {'SVP64BREV': Const(0, 1),
+ 'SVP64FFT': Const(0, 1),
}
self.actually_does_something = False
self.pname = name
self.ccases = {}
self.ckeys = list(conditions.keys())
self.ckeys.sort()
- cswitch = []
- for i, ckey in enumerate(self.ckeys):
- case = ['-'] * len(self.ckeys)
- case[i] = '1'
- self.ccases[ckey] = ''.join(case)
- cswitch.append(conditions[ckey])
- self.cswitch = cswitch
def find_conditions(self, opcodes):
# look for conditions, create dictionary entries for them
opcode = row['opcode']
if condition:
# check it's expected
- assert condition in self.conditions, \
+ assert (condition in self.conditions or
+ (condition[0] == '~' and
+ condition[1:] in self.conditions)), \
"condition %s not in %s" % (condition, str(conditions))
if opcode not in rows:
rows[opcode] = {}
subdecoder = PowerDecoder(width=32, dec=sd,
name=mname,
col_subset=self.col_subset,
- row_subset=self.row_subsetfn)
+ row_subset=self.row_subsetfn,
+ conditions=self.conditions)
if not subdecoder.tree_analyse():
del subdecoder
continue
if is_conditions:
switch_case[opcode] = {}
for k, crow in row.items():
+ # log("ordered", k, crow)
switch_case[opcode][k] = self.op._eq(crow)
else:
switch_case[opcode] = self.op._eq(row)
subdecoder = PowerDecoder(self.width, dec,
name=mname,
col_subset=self.col_subset,
- row_subset=self.row_subsetfn)
+ row_subset=self.row_subsetfn,
+ conditions=self.conditions)
log ("subdecoder", mname, subdecoder)
if not subdecoder.tree_analyse(): # doesn't do anything
log ("analysed, DELETING", mname)
entries for a given opcode match. here we discern them.
"""
comb = m.d.comb
- with m.Switch(Cat(*self.cswitch)):
- for ckey, eqs in cases.items():
- with m.Case(self.ccases[ckey]):
+ cswitch = []
+ ccases = []
+ for casekey, eqs in cases.items():
+ if casekey.startswith('~'):
+ with m.If(~self.conditions[casekey[1:]]):
+ comb += eqs
+ else:
+ with m.If(self.conditions[casekey]):
comb += eqs
def ports(self):
return m
def ports(self):
- return [self.raw_opcode_in, self.bigendian] + PowerDecoder.ports(self)
+ res = [self.raw_opcode_in, self.bigendian] + PowerDecoder.ports(self)
+ for condition in self.conditions.values():
+ res.append(condition)
+ return res
#############################################################
# PRIMARY FUNCTION SPECIFYING THE FULL POWER DECODER
def create_pdecode(name=None, col_subset=None, row_subset=None,
- include_fp=False):
+ include_fp=False, conditions=None):
"""create_pdecode - creates a cascading hierarchical POWER ISA decoder
subsetting of the PowerOp decoding is possible by setting col_subset
bitsel=(0, 32), suffix=None, subdecoders=[]))
return TopPowerDecoder(32, dec, name=name, col_subset=col_subset,
- row_subset=row_subset)
+ row_subset=row_subset,
+ conditions=conditions)
+
+# test function from
+#https://github.com/apertus-open-source-cinema/naps/blob/9ebbc0/naps/soc/cli.py#L17
+def fragment_repr(original):
+ from textwrap import indent
+ attrs_str = "\n"
+ for attr in ['ports', 'drivers', 'statements', 'attrs',
+ 'generated', 'flatten']:
+ attrs_str += f"{attr}={repr(getattr(original, attr))},\n"
+
+ domains_str = "\n"
+ for name, domain in original.domains.items():
+ # TODO: this is not really sound because domains could be non local
+ domains_str += f"{name}: {domain.name}\n"
+ attrs_str += f"domains={{{indent(domains_str, ' ')}}},\n"
+
+ children_str = "\n"
+ for child, name in original.subfragments:
+ children_str += f"[{name}, {fragment_repr(child)}]\n"
+ attrs_str += f"children=[{indent(children_str, ' ')}],\n"
+
+ return f"Fragment({indent(attrs_str, ' ')})"
if __name__ == '__main__':
def rowsubsetfn(opcode, row):
log("row_subset", opcode, row)
- return row['unit'] == 'FPU'
+ return row['unit'] in ['LDST', 'FPU']
+ conditions = {'SVP64BREV': Signal(name="svp64brev", reset_less=True),
+ 'SVP64FFT': Signal(name="svp64fft", reset_less=True),
+ }
pdecode = create_pdecode(name="rowsub",
col_subset={'opcode', 'function_unit',
- 'form'},
+ 'asmcode',
+ 'in2_sel', 'in3_sel'},
row_subset=rowsubsetfn,
- include_fp=True)
+ include_fp=True,
+ conditions=conditions)
vl = rtlil.convert(pdecode, ports=pdecode.ports())
with open("row_subset_decoder.il", "w") as f:
f.write(vl)
+ vl = verilog.convert(pdecode, ports=pdecode.ports())
+ with open("row_subset_decoder.v", "w") as f:
+ f.write(vl)
+
# col subset
- pdecode = create_pdecode(name="fusubset", col_subset={'function_unit'})
+ pdecode = create_pdecode(name="fusubset", col_subset={'function_unit'},
+ conditions=conditions)
vl = rtlil.convert(pdecode, ports=pdecode.ports())
with open("col_subset_decoder.il", "w") as f:
f.write(vl)
+ from nmigen.hdl.ir import Fragment
+ elaborated = Fragment.get(pdecode, platform=None)
+ elaborated_repr = fragment_repr(elaborated)
+ print (elaborated_repr)
+
+ exit(0)
+
+ exit(0)
+
# full decoder
pdecode = create_pdecode(include_fp=True)
vl = rtlil.convert(pdecode, ports=pdecode.ports())
vl = rtlil.convert(pdecode, ports=pdecode.ports())
with open("decoder_svp64.il", "w") as f:
f.write(vl)
+
+