Move predicate collection into TargetISA.
Add a TargetISA.finish() method which computes derived data structures after the ISA definitions have been loaded.
This commit is contained in:
@@ -955,6 +955,37 @@ class TargetISA(object):
|
|||||||
self.instruction_groups = instruction_groups
|
self.instruction_groups = instruction_groups
|
||||||
self.cpumodes = list()
|
self.cpumodes = list()
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
"""
|
||||||
|
Finish the definition of a target ISA after adding all CPU modes and
|
||||||
|
settings.
|
||||||
|
|
||||||
|
This computes some derived properties that are used in multilple
|
||||||
|
places.
|
||||||
|
|
||||||
|
:returns self:
|
||||||
|
"""
|
||||||
|
self._collect_instruction_predicates()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def _collect_instruction_predicates(self):
|
||||||
|
"""
|
||||||
|
Collect and number all instruction predicates in use.
|
||||||
|
|
||||||
|
Sets `instp.number` for all used instruction predicates and places them
|
||||||
|
in `self.all_instps` in numerical order.
|
||||||
|
"""
|
||||||
|
self.all_instps = list()
|
||||||
|
instps = set()
|
||||||
|
for cpumode in self.cpumodes:
|
||||||
|
for enc in cpumode.encodings:
|
||||||
|
instp = enc.instp
|
||||||
|
if instp and instp not in instps:
|
||||||
|
# assign predicate number starting from 0.
|
||||||
|
instp.number = len(instps)
|
||||||
|
instps.add(instp)
|
||||||
|
self.all_instps.append(instp)
|
||||||
|
|
||||||
|
|
||||||
class CPUMode(object):
|
class CPUMode(object):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -75,10 +75,11 @@ def emit_instp(instp, fmt):
|
|||||||
# the field names.
|
# the field names.
|
||||||
fields = ', '.join(sorted(set(p.field.name for p in leafs)))
|
fields = ', '.join(sorted(set(p.field.name for p in leafs)))
|
||||||
|
|
||||||
with fmt.indented(
|
with fmt.indented('{} => {{'.format(instp.number), '}'):
|
||||||
'if let {} {{ {}, .. }} = *inst {{'
|
with fmt.indented(
|
||||||
.format(iform.name, fields), '}'):
|
'if let {} {{ {}, .. }} = *inst {{'
|
||||||
fmt.line('return {};'.format(instp.rust_predicate(0)))
|
.format(iform.name, fields), '}'):
|
||||||
|
fmt.line('return {};'.format(instp.rust_predicate(0)))
|
||||||
|
|
||||||
|
|
||||||
def emit_instps(instps, fmt):
|
def emit_instps(instps, fmt):
|
||||||
@@ -90,9 +91,8 @@ def emit_instps(instps, fmt):
|
|||||||
'fn check_instp(inst: &InstructionData, instp_idx: u16) -> bool {',
|
'fn check_instp(inst: &InstructionData, instp_idx: u16) -> bool {',
|
||||||
'}'):
|
'}'):
|
||||||
with fmt.indented('match instp_idx {', '}'):
|
with fmt.indented('match instp_idx {', '}'):
|
||||||
for (instp, idx) in instps.items():
|
for instp in instps:
|
||||||
with fmt.indented('{} => {{'.format(idx), '}'):
|
emit_instp(instp, fmt)
|
||||||
emit_instp(instp, fmt)
|
|
||||||
fmt.line('_ => panic!("Invalid instruction predicate")')
|
fmt.line('_ => panic!("Invalid instruction predicate")')
|
||||||
|
|
||||||
# The match cases will fall through if the instruction format is wrong.
|
# The match cases will fall through if the instruction format is wrong.
|
||||||
@@ -102,17 +102,6 @@ def emit_instps(instps, fmt):
|
|||||||
fmt.line(' instp_idx);')
|
fmt.line(' instp_idx);')
|
||||||
|
|
||||||
|
|
||||||
def collect_instps(cpumodes):
|
|
||||||
# Map instp -> number
|
|
||||||
instps = OrderedDict()
|
|
||||||
for cpumode in cpumodes:
|
|
||||||
for enc in cpumode.encodings:
|
|
||||||
instp = enc.instp
|
|
||||||
if instp and instp not in instps:
|
|
||||||
instps[instp] = 1 + len(instps)
|
|
||||||
return instps
|
|
||||||
|
|
||||||
|
|
||||||
class EncList(object):
|
class EncList(object):
|
||||||
"""
|
"""
|
||||||
List of instructions for encoding a given type + opcode pair.
|
List of instructions for encoding a given type + opcode pair.
|
||||||
@@ -192,13 +181,12 @@ def make_tables(cpumode):
|
|||||||
return table
|
return table
|
||||||
|
|
||||||
|
|
||||||
def gen_isa(cpumodes, fmt):
|
def gen_isa(isa, fmt):
|
||||||
# First assign numbers to relevant instruction predicates and generate the
|
# First assign numbers to relevant instruction predicates and generate the
|
||||||
# check_instp() function..
|
# check_instp() function..
|
||||||
instps = collect_instps(cpumodes)
|
emit_instps(isa.all_instps, fmt)
|
||||||
emit_instps(instps, fmt)
|
|
||||||
|
|
||||||
for cpumode in cpumodes:
|
for cpumode in isa.cpumodes:
|
||||||
level1 = make_tables(cpumode)
|
level1 = make_tables(cpumode)
|
||||||
for level2 in level1:
|
for level2 in level1:
|
||||||
for enclist in level2:
|
for enclist in level2:
|
||||||
@@ -210,5 +198,5 @@ def gen_isa(cpumodes, fmt):
|
|||||||
def generate(isas, out_dir):
|
def generate(isas, out_dir):
|
||||||
for isa in isas:
|
for isa in isas:
|
||||||
fmt = srcgen.Formatter()
|
fmt = srcgen.Formatter()
|
||||||
gen_isa(isa.cpumodes, fmt)
|
gen_isa(isa, fmt)
|
||||||
fmt.update_file('encoding-{}.rs'.format(isa.name), out_dir)
|
fmt.update_file('encoding-{}.rs'.format(isa.name), out_dir)
|
||||||
|
|||||||
@@ -26,8 +26,7 @@ RV32G / RV64G
|
|||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from . import defs
|
from . import defs
|
||||||
from . import encodings
|
from . import encodings, settings # noqa
|
||||||
from . import settings
|
|
||||||
|
|
||||||
# Re-export the primary target ISA definition.
|
# Re-export the primary target ISA definition.
|
||||||
isa = defs.isa
|
isa = defs.isa.finish()
|
||||||
|
|||||||
Reference in New Issue
Block a user