diff --git a/unoptimized_lr/simple_lr_automaton.py b/unoptimized_lr/simple_lr_automaton.py index a3d964568e721f7e92359de40e654db98561ea76..77c486ef509bf11f791842b76e02618f4269ac73 100644 --- a/unoptimized_lr/simple_lr_automaton.py +++ b/unoptimized_lr/simple_lr_automaton.py @@ -26,6 +26,7 @@ from functools import reduce # * NNonterminal: Number of nonterminals # * NStates: Number of states in the LR automaton # * NRules: Number of rules +# * NLongestRule: Maximum number of right-hand-side items in a language rule # # From those, we derive these widths for internal buses and registers, # where log_2 determines the numbers of bits necessary to represent all possible @@ -35,6 +36,7 @@ from functools import reduce # log_2(NNonterminal) = WNonterminal # log_2(NStates)= WStates # log_2(NRules)= WRules +# log_2(NLongestRule)= WLongestRule # and WItem = max(WTerminal, WNonterminal); since there are locations where # nonterminals and terminals alike must be processed/stored by the same mechanisms # @@ -43,6 +45,9 @@ from functools import reduce # * NStackItems: Parse stack depth. # * NLongestParse: The length of the longest possible parse tree # +# log_2(NStackItems) = WStackItems +# log_2(NLongestParse) = WLongestParse +# # In the general case, it is impossible to determine these for a given language. # Even with a simple expression-term-factor grammar, it's possible to reach arbitrary # depth of parse stack with arbitrary numbers of OPENPARENs, and likewise for the @@ -60,14 +65,121 @@ from functools import reduce # * Parse Stack # * Sideband/index stack # * Serialization memory +# +# +# The top-level parser state machine ingests tokens from the input (with a bit width of +# WTerminal): +# +# INPUT STREAM +# | +# | bitwidth = WTerminal +# | +# V +# /----------------------\ +# | Parse State Machine | +# \----------------------/ +# +# And the Parse State Machine is interfaced with multiple subcomponents. None of the +# subcomponents are connected to each other so we list them here without needing to +# include them in a single block diagram +# +# +# Shift/Reduce table: +# +# (current state number, current terminal) +# WStates WTerminal +# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# / \ +# /----------------------\ /---------------------\ +# | Parse State Machine | | Shift/reduce lookup | +# \----------------------/ \---------------------/ +# \ / +# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +# (Parser action: {shift terminal, accept, error, reduce with rule k}) +# +# +# +# GOTO table: +# +# (current state number, nonterminal created by reduce rule) +# WStates WNonterminal +# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# / \ +# /----------------------\ /---------------------\ +# | Parse State Machine | | GOTO Table | +# \----------------------/ \---------------------/ +# \ / +# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +# (validity bit, next state number) +# +# +# +# Reduce rule table: +# +# (reduce rule number) +# WRules +# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# / \ +# /----------------------\ /---------------------\ +# | Parse State Machine | | Reduce Rule Table | +# \----------------------/ \---------------------/ +# \ / +# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +# (nonterminal created, number of stack items to pop) +# +# +# +# Parse item stack: +# +# (stack operation type, index for multipop, state number to push) +# 3 bits WStackItems WStates +# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# / \ +# /----------------------\ /---------------------\ +# | Parse State Machine | | Parse item stack | +# \----------------------/ \---------------------/ +# \ / +# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +# (index out, data out, stack pointer) +# +# +# +# Parse index stack. Note that this is only needed if we're outputting a +# serialized parse tree (regardless if to memory or to a stream): +# +# (stack operation type, index for multipop, serialization index to push) +# 3 bits WStackItems WLongestParse +# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# / \ +# /----------------------\ /---------------------\ +# | Parse State Machine | | Parse index stack | +# \----------------------/ \---------------------/ +# \ / +# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +# (index out, data out, stack pointer) +# +# +# Serialization memory (or stream): +# +# max(WLongestRule, 1 + WNonterminal, 1 + WTerminal) +# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +# / \ +# /----------------------\ /---------------------\ +# | Parse State Machine | | Serialization memory| +# \----------------------/ \---------------------/ +# +# Note that there is no read connection, this allows the serialization memory +# interface to be used without any change for a stream interface +# + + -class LRAutomaton(Elaboratable): +class SimpleLRAutomaton(Elaboratable): def __init__(self): - # Stack self.mem = Memory(width=self.table_width, depth=self.table_depth, init=rasterized)