ruby: slicc method error fix
[gem5.git] / src / mem / slicc / README
1 Overview
2 ========
3 This is SLICC, a domain specific language to specify cache coherence protocol
4 we have developed in Multifacet group.
5
6 It is developed by Milo Martin <milo@cs.wisc.edu>
7 This document is prepared by Min Xu <mxu@cae.wisc.edu> while I am learning the
8 system. With minor correctness updates by Brad Beckmann <beckmann@cs.wisc.edu>
9
10 It can be used to generate C++ code that works with RUBY cache simulator as
11 well as generate HTML and other document to describe the target protocol.
12
13 Some user document is available in doc directory.
14
15 Tech details
16 ============
17 SLICC take a text input with similar syntax to C++ language and use the lexer
18 and parser in parser directory to construct a Abstract Syntax Tree (AST)
19 internally. After having done this first pass, the AST is traversed to fill
20 several interval table, such as symbol table, type table, etc. Finally the code
21 is generated by traversing the tree once again.
22
23 Note, by Milo's good coding habit, almost all C++ class define their private
24 copy/assignment constructor. This prevents accidentally copying/assigning an
25 object by its address.
26
27 The AST basically looks like a hierarchical representation of the text input.
28 At the highest level, it has the "Machine", each Machine has several "states"
29 and "events" and "actions" and "transistions".
30
31 Since the language is domain specific, many assumptions of the target system is
32 hardcoded in SLICC. For example, ruby would expect the generated code for each
33 system node, has the following components:
34 processor(sequencer, not generated?)
35 cache
36 directory (with memory block value, only when compiled with tester)
37 network interface (NI)
38
39 Directory generator/ contains routines to generate HTML/MIF format output.
40 fileio.[Ch] has a routine to conditionally write a file only when the original
41 content of the file is different from what is going to be written, this avoid
42 re-make those file after regenerate the protocol. html_gen.[Ch] contains the
43 symbol name munge and index page generation. mif_gen.[Ch] contains the entire
44 MIF output generation routine, mainly a table buildup.
45
46 Directory symbol/ contains classes to represent symbols in the slicc input
47 file. Base class is "Symbol". Derived subclasses are "Action Event Func State
48 StateMachine Transition Type Var". "Symbol" has knowledge about its locations
49 in the source file and short name, long name. "SymbolTable" is a list of
50 symbols and g_sym_table is the global SymbolTable of the slicc system.
51 One can query a SymbolTable by symbol's id. Also SymbolTable is responsible for
52 keeping track of Symbol's declaration in correct scope. The current
53 implementation uses a stack which dynamically determine the scope of symbol
54 lookups. Global scope is at bottom of the stack (vector[0]). SymbolTable is
55 also the main place to write out the generated C++/HTML/MIF files.
56 SymbolTable::writeNodeFiles() is one of the place to look for hardcoded C++
57 code for node.[Ch]. And Type.[Ch] is the place where generating enumeration and
58 Message/NetworkMessage declaration and implementation. Func.[Ch] is used to
59 generate function of the class Chip. StateMachine.[Ch] wrap the whole thing
60 up by putting States, Actions, Events together. It actually has a two dimension
61 table like the one represented in the HTML output. Actions are indexed with
62 the initial state and observed event. After the tabel being built, the
63 StateMachine class can write out Transitions/Controller/wakeup_logic into C++
64 outputs. Finally, in symbol directory, Var.[Ch] seem to incomplete?
65
66 Demystify all those "predefined" external types, like "Address". Where are
67 they defined? They are in ../protocol/RubySlicc-*.sm and
68 ../protocol/RubySlicc_interfaces.slicc is include in the slicc invocation
69 command in ../ruby/Makefile.
70
71 Another myth: "trigger" method is hardcoded in ast/InPortDeclAST.C and
72 ast/FuncCallExprAST.C. The function is similar to inlined function in the
73 output generated code, so you cannot find any occurance of string "trigger" in
74 the generated code. "trigger" also increment a counter that is checked every
75 time a transition is done. In one ruby cycle, only TRANSITIONS_PER_RUBY_CYCLE
76 number of transitions can be done. ast/FuncCallExprAST.C also contains some
77 code for function "error" and "assert" and "DEBUG_EXPR", all in the same
78 manner. Ruby always issues transitions from the first port while there is any.
79 Stalled transition in Ruby does not consume a sub-cycle. This models the
80 hardware that probe all port in parallel, pick one transition from the highest
81 priority queue if the transistion was not stalled by any resources constraint.
82
83 Another note: scheduleEvent() call of ruby make sure a consumer is woken up at
84 specified cycle, and only once per cycle.
85
86 Action z_stall, where is it? It is hardcoded in symbols/StateMachine.C. In
87 function StateMachine::printCSwitch(), z_stall cause the generated code return
88 TransitionResult_ProtocolStall. Also the HTML output for z_stall has to be
89 consequently hardcoded. I am not sure that's really a good idea or not. :-)
90
91 Question: How comes there is no "for" loop statement in slicc?
92 Answer: Been there, done that. That is easy to add, first of all. But unbound
93 loop make slicc eventually un-synthesizable. We want to avoid that. If you want
94 to loop through a bounded array do something, make the action done in a
95 external interface in RubySlicc_Util.h. Inside, you just pass the vector as
96 parameter to the external interface to achieve the same effects.
97
98 Another bad thing of using loop statement like for is that we can not determine
99 how many buffer space to allocate before the transition. With a vector, if it
100 easy to understand we can always allocate the worst case number of hardware
101 resources.
102
103 Question: Wait! It seems statement check_allocate does nothing!
104 Answer: No, it does call areNSoltsAvailable() function of the object before any
105 statement is executed in one action. It does *NOT* generate code in its
106 original place in the code, instead, it scan the body of the action code and
107 determine how many slots are needed to allocated before hand. So the
108 transaction is all done or nothing done. I had tried to make all actions return
109 boolean values and the false return cause a transition to abort with
110 ResourceStall. But it is later on deemed to be too flexible in its semantics.
111 We should never introduce control flow inside the transitions, so that each
112 transition is either "all" or "nothing". Just that simple. BTW, if you call
113 check_allocate twice, areNSoltsAvailable(2) is generated, three times generates
114 areNSoltsAvailable(3), etc.