ruby: slicc: remove README
No longer maintained. Updates are only made to the wiki page. So being dropped.
This commit is contained in:
parent
0647d99854
commit
57971248f6
1 changed files with 0 additions and 114 deletions
|
@ -1,114 +0,0 @@
|
||||||
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 <milo@cs.wisc.edu>
|
|
||||||
This document is prepared by Min Xu <mxu@cae.wisc.edu> while I am learning the
|
|
||||||
system. With minor correctness updates by Brad Beckmann <beckmann@cs.wisc.edu>
|
|
||||||
|
|
||||||
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.
|
|
Loading…
Reference in a new issue