Gabe Black has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/56334 )
Change subject: arch-x86: Simplify and reorganize the grammar for the ucode
asm.
......................................................................
arch-x86: Simplify and reorganize the grammar for the ucode asm.
Change-Id: Ibee8d548c1d7ef6ff0ee1612bf547ea53f2e3d54
---
M src/arch/micro_asm.py
M src/arch/x86/isa/macroop.isa
M src/arch/x86/isa/rom.isa
3 files changed, 119 insertions(+), 160 deletions(-)
diff --git a/src/arch/micro_asm.py b/src/arch/micro_asm.py
index 0bf9caa..da52a61 100644
--- a/src/arch/micro_asm.py
+++ b/src/arch/micro_asm.py
@@ -53,6 +53,9 @@
microop.micropc = len(self.microops)
self.microops.append(microop)
+ def add_label(self, label):
+ self.labels[label.name] = len(self.microops)
+
def __str__(self):
string = "%s:\n" % self.name
for microop in self.microops:
@@ -75,39 +78,68 @@
super().__init__(name)
self.externs = {}
+ def add_label(self, label):
+ super().add_label(label)
+ if label.is_extern:
+ self.externs[label.name] = len(self.microops)
+
##########################################################################
#
# Support classes
#
##########################################################################
-class Label(object):
- def __init__(self):
- self.extern = False
- self.name = ""
-
-class Block(object):
+class Block:
def __init__(self):
self.statements = []
-class Statement(object):
- def __init__(self):
- self.is_microop = False
- self.is_directive = False
- self.name = ""
- self.params = ""
+class Statement:
+ def __init__(self, name, is_directive=False):
+ self.name = name
+ self.is_directive = is_directive
class Microop(Statement):
- def __init__(self):
- super().__init__()
- self.labels = []
- self.is_microop = True
+ def __init__(self, name, params):
+ super().__init__(name)
+ self.params = params
+
+ def handle(self, parser, container):
+ microop = parser.microops.get(self.name, None)
+ if not microop:
+ raise Exception(f'Unrecongized mnemonic: "{self.name}"')
+
+ try:
+ microop = eval(f'_cls({self.params})',
+ {'_cls': microop}, parser.symbols)
+ except:
+ print_error(f'Error instantiating microop "{self.name}"')
+ raise
+
+ container.add_microop(self.name, microop)
class Directive(Statement):
- def __init__(self):
- super().__init__()
- self.name = ""
- self.is_directive = True
+ def __init__(self, name, params):
+ super().__init__(name, True)
+ self.params = params
+
+ def handle(self, parser, container):
+ directive = container.directives.get(self.name, None)
+ if not directive:
+ raise Exception(f'Unrecognized directive: "{self.name}"')
+ local = {'_dir': directive}
+ try:
+ eval(f'_dir({self.params})', {'_dir': directive},
parser.symbols)
+ except:
+ print_error(f'Error executing directive "{self.name}"')
+ raise
+
+class Label(Statement):
+ def __init__(self, name, is_extern):
+ super().__init__(name)
+ self.is_extern = is_extern
+
+ def handle(self, parser, container):
+ container.add_label(self)
##########################################################################
#
@@ -120,38 +152,6 @@
print("*** %s" % message)
print()
-def handle_statement(parser, container, statement):
- name = statement.name
- params = statement.params
-
- if statement.is_microop:
- if name not in parser.microops:
- raise Exception(f'Unrecognized mnemonic: "{name}"')
- local = {'_cls': parser.microops[name]}
- try:
- microop = eval(f'_cls({params})', local, parser.symbols)
- except:
- print_error(f'Error creating "{name}" microop object.')
- raise
-
- for label in statement.labels:
- container.labels[label.text] = microop
- if label.is_extern:
- container.externs[label.text] = microop
- container.add_microop(name, microop)
-
- elif statement.is_directive:
- if name not in container.directives:
- raise Exception(f'Unrecognized directive: "{name}"')
- local = {'_dir': container.directives[name]}
- try:
- eval(f'_dir({params})', local, parser.symbols)
- except:
- print_error(f'Error executing directive "{name}".')
- raise
- else:
- raise Exception(f"Didn't recognize the type of statement
{statement}")
-
##########################################################################
#
# Lexer specification
@@ -310,39 +310,37 @@
#
##########################################################################
-# Start symbol for a file which may have more than one macroop or rom
-# specification.
+# Start symbol for a file which may have more than one "object" defined in
it.
def p_file(t):
- 'file : opt_rom_or_macros'
+ 'file : opt_objects'
-def p_opt_rom_or_macros_0(t):
- 'opt_rom_or_macros : '
+# The objects are optional.
+def p_opt_objects(t):
+ '''opt_objects : objects
+ |'''
-def p_opt_rom_or_macros_1(t):
- 'opt_rom_or_macros : rom_or_macros'
+# One or more objects.
+def p_objects(t):
+ '''objects : objects object
+ | object'''
-def p_rom_or_macros_0(t):
- 'rom_or_macros : rom_or_macro'
+# Objects can be of various types.
+def p_object(t):
+ '''object : rom_block
+ | macroop_def'''
-def p_rom_or_macros_1(t):
- 'rom_or_macros : rom_or_macros rom_or_macro'
-
-def p_rom_or_macro_0(t):
- '''rom_or_macro : rom_block
- | macroop_def'''
-
-# Defines a section of microcode that should go in the current ROM
+# Defines a section of microcode that should go in the current ROM.
def p_rom_block(t):
'rom_block : DEF ROM block SEMI'
if not t.parser.rom:
print_error("Rom block found, but no Rom object specified.")
raise TypeError("Rom block found, but no Rom object was
specified.")
for statement in t[3].statements:
- handle_statement(t.parser, t.parser.rom, statement)
+ statement.handle(t.parser, t.parser.rom)
t[0] = t.parser.rom
-# Defines a macroop that jumps to an external label in the ROM
-def p_macroop_def_0(t):
+# Defines a macroop that jumps to an external label in the ROM.
+def p_macroop_jump(t):
'macroop_def : DEF MACROOP ID LPAREN ID RPAREN SEMI'
if not t.parser.rom_macroop_type:
print_error("ROM based macroop found, but no ROM macroop " +
@@ -353,8 +351,8 @@
t.parser.macroops[t[3]] = macroop
-# Defines a macroop that is combinationally generated
-def p_macroop_def_1(t):
+# Defines a macroop that is combinationally generated.
+def p_macroop_def(t):
'macroop_def : DEF MACROOP ID block SEMI'
try:
curop = t.parser.macro_type(t[3])
@@ -362,7 +360,7 @@
print_error("Error creating macroop object.")
raise
for statement in t[4].statements:
- handle_statement(t.parser, curop, statement)
+ statement.handle(t.parser, curop)
t.parser.macroops[t[3]] = curop
# A block of statements
@@ -372,12 +370,10 @@
block.statements = t[2]
t[0] = block
+# One or more statements
def p_statements_0(t):
'statements : statement'
- if t[1]:
- t[0] = [t[1]]
- else:
- t[0] = []
+ t[0] = [t[1]] if t[1] else []
def p_statements_1(t):
'statements : statements statement'
@@ -385,98 +381,52 @@
t[1].append(t[2])
t[0] = t[1]
+# A statement can be of various types.
def p_statement(t):
- 'statement : content_of_statement end_of_statement'
+ '''statement : empty_statement
+ | label
+ | microop
+ | directive'''
t[0] = t[1]
-# A statement can be a microop or an assembler directive
-def p_content_of_statement_0(t):
- '''content_of_statement : microop
- | directive'''
+# Parameters are optional.
+def p_opt_params_0(t):
+ 'opt_params : PARAMS'
t[0] = t[1]
-# Ignore empty statements
-def p_content_of_statement_1(t):
- 'content_of_statement : '
- pass
+def p_opt_params_1(t):
+ 'opt_params :'
+ t[0] = ""
-# Statements are ended by newlines or a semi colon
+# Statements are often ended by newlines or a semi colon.
def p_end_of_statement(t):
'''end_of_statement : NEWLINE
| SEMI'''
pass
-# Different flavors of microop to avoid shift/reduce errors
-def p_microop_0(t):
- 'microop : labels ID'
- microop = Microop()
- microop.labels = t[1]
- microop.name = t[2]
- t[0] = microop
+# Ignore empty statements.
+def p_empty_statement(t):
+ 'empty_statement : end_of_statement'
+ pass
-def p_microop_1(t):
- 'microop : ID'
- microop = Microop()
- microop.name = t[1]
- t[0] = microop
-
-def p_microop_2(t):
- 'microop : labels ID PARAMS'
- microop = Microop()
- microop.labels = t[1]
- microop.name = t[2]
- microop.params = t[3]
- t[0] = microop
-
-def p_microop_3(t):
- 'microop : ID PARAMS'
- microop = Microop()
- microop.name = t[1]
- microop.params = t[2]
- t[0] = microop
-
-# Labels in the microcode
-def p_labels_0(t):
- 'labels : label'
- t[0] = [t[1]]
-
-def p_labels_1(t):
- 'labels : labels label'
- t[1].append(t[2])
- t[0] = t[1]
-
-# labels on lines by themselves are attached to the following instruction.
-def p_labels_2(t):
- 'labels : labels NEWLINE'
- t[0] = t[1]
-
+# A label in the microcode.
def p_label_0(t):
- 'label : ID COLON'
- label = Label()
- label.is_extern = False
- label.text = t[1]
- t[0] = label
+ 'label : EXTERN ID COLON'
+ t[0] = Label(t[2], True)
def p_label_1(t):
- 'label : EXTERN ID COLON'
- label = Label()
- label.is_extern = True
- label.text = t[2]
- t[0] = label
+ 'label : ID COLON'
+ t[0] = Label(t[1], False)
-# Directives for the macroop
-def p_directive_0(t):
- 'directive : DOT ID'
- directive = Directive()
- directive.name = t[2]
- t[0] = directive
+# A microop with optional parameters.
+def p_microop(t):
+ 'microop : ID opt_params end_of_statement'
+ t[0] = Microop(t[1], t[2])
-def p_directive_1(t):
- 'directive : DOT ID PARAMS'
- directive = Directive()
- directive.name = t[2]
- directive.params = t[3]
- t[0] = directive
+# Directives for the macroop.
+def p_directive(t):
+ 'directive : DOT ID opt_params end_of_statement'
+ t[0] = Directive(t[2], t[3])
# Parse error handler. Note that the argument here is the offending
# *token*, not a grammar symbol (hence the need to use t.value)
diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa
index 8bd3b7e..07f8a02 100644
--- a/src/arch/x86/isa/macroop.isa
+++ b/src/arch/x86/isa/macroop.isa
@@ -197,9 +197,9 @@
#FIXME This first parameter should be the mnemonic. I need to
#write some code which pulls that out
declareLabels = ""
- for (label, microop) in self.labels.items():
+ for (label, micropc) in self.labels.items():
declareLabels += "const static uint64_t label_%s = %d;\n" \
- % (label, microop.micropc)
+ % (label, micropc)
iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
{"code" : "",
"declareLabels" : declareLabels
diff --git a/src/arch/x86/isa/rom.isa b/src/arch/x86/isa/rom.isa
index 93f4401..d53c9de 100644
--- a/src/arch/x86/isa/rom.isa
+++ b/src/arch/x86/isa/rom.isa
@@ -30,13 +30,13 @@
class X86MicrocodeRom(Rom):
def getDeclaration(self):
declareLabels = "namespace rom_labels\n{\n"
- for (label, microop) in self.labels.items():
+ for (label, micropc) in self.labels.items():
declareLabels += "const static uint64_t label_%s = %d;\n" \
- % (label, microop.micropc)
- for (label, microop) in self.externs.items():
+ % (label, micropc)
+ for (label, micropc) in self.externs.items():
declareLabels += \
"const static MicroPC extern_label_%s = %d;\n" \
- % (label, microop.micropc)
+ % (label, micropc)
declareLabels += "}\n"
return declareLabels;
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/56334
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ibee8d548c1d7ef6ff0ee1612bf547ea53f2e3d54
Gerrit-Change-Number: 56334
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s