From 2f30950143cc70bc42a3c8a4111d7cf8198ec881 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 11 May 2009 10:38:43 -0700 Subject: ruby: Import ruby and slicc from GEMS We eventually plan to replace the m5 cache hierarchy with the GEMS hierarchy, but for now we will make both live alongside eachother. --- src/mem/slicc/README | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/mem/slicc/README (limited to 'src/mem/slicc/README') diff --git a/src/mem/slicc/README b/src/mem/slicc/README new file mode 100644 index 000000000..fb7f52dac --- /dev/null +++ b/src/mem/slicc/README @@ -0,0 +1,114 @@ +Overview +======== +This is SLICC, a domain specific language to specify cache coherence protocol +we have developed in Multifacet group. + +It is developed by Milo Martin +This document is prepared by Min Xu while I am learning the +system. With minor correctness updates by Brad Beckmann + +It can be used to generate C++ code that works with RUBY cache simulator as +well as generate HTML and other document to describe the target protocol. + +Some user document is available in doc directory. + +Tech details +============ +SLICC take a text input with similar syntax to C++ language and use the lexer +and parser in parser directory to construct a Abstract Syntax Tree (AST) +internally. After having done this first pass, the AST is traversed to fill +several interval table, such as symbol table, type table, etc. Finally the code +is generated by traversing the tree once again. + +Note, by Milo's good coding habit, almost all C++ class define their private +copy/assignment constructor. This prevents accidentally copying/assigning an +object by its address. + +The AST basically looks like a hierarchical representation of the text input. +At the highest level, it has the "Machine", each Machine has several "states" +and "events" and "actions" and "transistions". + +Since the language is domain specific, many assumptions of the target system is +hardcoded in SLICC. For example, ruby would expect the generated code for each +system node, has the following components: + processor(sequencer, not generated?) + cache + directory (with memory block value, only when compiled with tester) + network interface (NI) + +Directory generator/ contains routines to generate HTML/MIF format output. +fileio.[Ch] has a routine to conditionally write a file only when the original +content of the file is different from what is going to be written, this avoid +re-make those file after regenerate the protocol. html_gen.[Ch] contains the +symbol name munge and index page generation. mif_gen.[Ch] contains the entire +MIF output generation routine, mainly a table buildup. + +Directory symbol/ contains classes to represent symbols in the slicc input +file. Base class is "Symbol". Derived subclasses are "Action Event Func State +StateMachine Transition Type Var". "Symbol" has knowledge about its locations +in the source file and short name, long name. "SymbolTable" is a list of +symbols and g_sym_table is the global SymbolTable of the slicc system. +One can query a SymbolTable by symbol's id. Also SymbolTable is responsible for +keeping track of Symbol's declaration in correct scope. The current +implementation uses a stack which dynamically determine the scope of symbol +lookups. Global scope is at bottom of the stack (vector[0]). SymbolTable is +also the main place to write out the generated C++/HTML/MIF files. +SymbolTable::writeNodeFiles() is one of the place to look for hardcoded C++ +code for node.[Ch]. And Type.[Ch] is the place where generating enumeration and +Message/NetworkMessage declaration and implementation. Func.[Ch] is used to +generate function of the class Chip. StateMachine.[Ch] wrap the whole thing +up by putting States, Actions, Events together. It actually has a two dimension +table like the one represented in the HTML output. Actions are indexed with +the initial state and observed event. After the tabel being built, the +StateMachine class can write out Transitions/Controller/wakeup_logic into C++ +outputs. Finally, in symbol directory, Var.[Ch] seem to incomplete? + +Demystify all those "predefined" external types, like "Address". Where are +they defined? They are in ../protocol/RubySlicc-*.sm and +../protocol/RubySlicc_interfaces.slicc is include in the slicc invocation +command in ../ruby/Makefile. + +Another myth: "trigger" method is hardcoded in ast/InPortDeclAST.C and +ast/FuncCallExprAST.C. The function is similar to inlined function in the +output generated code, so you cannot find any occurance of string "trigger" in +the generated code. "trigger" also increment a counter that is checked every +time a transition is done. In one ruby cycle, only TRANSITIONS_PER_RUBY_CYCLE +number of transitions can be done. ast/FuncCallExprAST.C also contains some +code for function "error" and "assert" and "DEBUG_EXPR", all in the same +manner. Ruby always issues transitions from the first port while there is any. +Stalled transition in Ruby does not consume a sub-cycle. This models the +hardware that probe all port in parallel, pick one transition from the highest +priority queue if the transistion was not stalled by any resources constraint. + +Another note: scheduleEvent() call of ruby make sure a consumer is woken up at +specified cycle, and only once per cycle. + +Action z_stall, where is it? It is hardcoded in symbols/StateMachine.C. In +function StateMachine::printCSwitch(), z_stall cause the generated code return +TransitionResult_ProtocolStall. Also the HTML output for z_stall has to be +consequently hardcoded. I am not sure that's really a good idea or not. :-) + +Question: How comes there is no "for" loop statement in slicc? +Answer: Been there, done that. That is easy to add, first of all. But unbound +loop make slicc eventually un-synthesizable. We want to avoid that. If you want +to loop through a bounded array do something, make the action done in a +external interface in RubySlicc_Util.h. Inside, you just pass the vector as +parameter to the external interface to achieve the same effects. + +Another bad thing of using loop statement like for is that we can not determine +how many buffer space to allocate before the transition. With a vector, if it +easy to understand we can always allocate the worst case number of hardware +resources. + +Question: Wait! It seems statement check_allocate does nothing! +Answer: No, it does call areNSoltsAvailable() function of the object before any +statement is executed in one action. It does *NOT* generate code in its +original place in the code, instead, it scan the body of the action code and +determine how many slots are needed to allocated before hand. So the +transaction is all done or nothing done. I had tried to make all actions return +boolean values and the false return cause a transition to abort with +ResourceStall. But it is later on deemed to be too flexible in its semantics. +We should never introduce control flow inside the transitions, so that each +transition is either "all" or "nothing". Just that simple. BTW, if you call +check_allocate twice, areNSoltsAvailable(2) is generated, three times generates +areNSoltsAvailable(3), etc. -- cgit v1.2.3