summaryrefslogtreecommitdiff
path: root/src/mem/slicc/doc
diff options
context:
space:
mode:
authorNathan Binkert <nate@binkert.org>2009-05-11 10:38:43 -0700
committerNathan Binkert <nate@binkert.org>2009-05-11 10:38:43 -0700
commit2f30950143cc70bc42a3c8a4111d7cf8198ec881 (patch)
tree708f6c22edb3c6feb31dd82866c26623a5329580 /src/mem/slicc/doc
parentc70241810d4e4f523f173c1646b008dc40faad8e (diff)
downloadgem5-2f30950143cc70bc42a3c8a4111d7cf8198ec881.tar.xz
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.
Diffstat (limited to 'src/mem/slicc/doc')
-rw-r--r--src/mem/slicc/doc/SLICC_V03.txt307
-rw-r--r--src/mem/slicc/doc/tutorial.tex574
2 files changed, 881 insertions, 0 deletions
diff --git a/src/mem/slicc/doc/SLICC_V03.txt b/src/mem/slicc/doc/SLICC_V03.txt
new file mode 100644
index 000000000..1c2a95a39
--- /dev/null
+++ b/src/mem/slicc/doc/SLICC_V03.txt
@@ -0,0 +1,307 @@
+SLICC - Version 0.3 Design Document - January 17, 1999
+Milo Martin and Dan Sorin
+
+Question: Rethinking of support for profiling the transactions
+
+Question: How do we deal with functions/methods and resources
+
+Comment: We need to discuss the sequencer interface so it can work now
+ and for the speculative version buffer.
+
+Overview
+--------
+
+We are in the process of designing and implementing SLICC v0.3, an
+evolution of SLICC v0.2. The new design includes capabilities for
+design of multilevel cache hierarchies including the specification of
+multiple protocol state machines (PSMs) and the queues which connect
+these PSMs and the network. We actually believe that most of the
+network and network topology, including the ordered network, can be
+expressed using the new hierarchical extensions to the language.
+
+In addition, many implicit aspects of the language will be eliminated
+in favor of explicit declarations. For example functions, queues, and
+objects declarations such as "cacheMemory" and "TBETable" will be
+explicitly declared. This will allow for full static type checking
+and easier extension for the language. Event triggering will be part
+of "in_port" declarations and not "event" declarations. Finally, many
+less fundamental, but important, features and internal code
+improvements will be enhanced.
+
+SLICC History
+-------------
+
+v0.1 - Initially the language only handled the generation of the PSM
+ transition table logic. All actions and event triggering were
+ still coded in C++. At this point it was still called, "the
+ language."
+
+v0.2 - Extended the language to include a simple C like syntax for
+ specifying actions, event triggering, and manipulating queues
+ and state elements. This version was the first version of the
+ language known as SLICC (suggested by Amir) and was used for
+ the Multifacet ISCA 2000 submission.
+
+v0.3 - Development effort started January 2000. Intended features and
+ enhancements are described by this document.
+
+Specifying Hierarchical Designs
+-------------------------------
+
+Right now all of our protocols have two tables, a processor/cache PSM
+and a directory PSM. In v0.2 this is a rigid requirement and
+the names are implicit. SLICC v0.3 will allow for an arbitrary number
+of different PSMs.
+
+The most significant improvement in v0.3 is the ability for the user
+to define an arbitrary set of interconnected PSMs. PSMs may include
+an L1 cache controller, L2 cache controller, directory controller,
+speculative version buffer, network interface, etc. There are a
+couple of "primitive PSMs" such as the sequencer.
+
+There will be a notion of a "node" of the system. In a node, each PSM
+will be instantiated and connected together with queues. For example,
+assume we define a PSMs and want to create a queue of RequestMessages
+to communicate between it and the network.
+
+ machine(CacheController) {
+ ...
+ out_port(to_network, RequestMessage, "To the network", desc="...");
+ ...
+ }
+
+ CacheController cache, desc="...";
+
+ connect(cache.to_network, network.from_cache, ordered="yes", desc="...");
+
+Explicit State Manipulation
+---------------------------
+
+As before, PSMs have states, events, and transitions. New in v0.3 each
+PSM must have user defined methods for get_state(address) and
+set_state(address, state), and these methods are written explicitly,
+instead of being implicit functions of memory states (e.g., our
+current implementation which implicitly uses the TBE state if there is
+a TBE or uses the cache state). Functions have a return value,
+procedures do not. Function calls are expressions, procedure calls
+are statements. All function and procedure parameters are considered
+pass-by-value.
+
+ procedure set_state(Address addr, State state) {
+ ...
+ }
+
+ function State get_state(Address addr) {
+ ...
+ }
+
+Explicit Declaration
+--------------------
+
+PSMs reference or declare structures, such as queues, ports, cache
+memories, main memory, TBEs, write buffers, etc. These primitive
+types and structures are written in C++, and their semantics are still
+specified by the C++ coder. Examples of these primitive types include
+"CacheMemory," "TBETable," as well as various types of queues.
+
+One major difference is that in v0.3 the interface for all of these
+primitive objects will be declared (but not defined) in the SLICC
+language. This also allows adding primitive structures by defining a
+C++ implementation and a SLICC interface specification. This will
+make the language much more extensible. Specifying the interface of
+these primitive types, structures, and queues in SLICC will eliminate
+much of the implicit semantics that is currently hiding in the
+controllers.
+
+The interface declaration might be in one file and shared between all
+protocols. The object instantiation would be internal to each PSM
+that requires a cache memory. The syntax for messages will also be
+enhanced by using this new syntax. Notice the support for default
+values.
+
+ structure(CacheMemory, "Cache memory", desc="...") {
+ void cache_change_state(Address addr, State state), desc="...";
+ Data dataBlk, default="", desc="";
+ bool cache_avail(Address addr), desc="...";
+ Address cache_probe(Address addr), desc="...";
+ void cache_allocate(Address addr), desc="...";
+ }
+
+ CacheMemory L1cacheMemory, desc="...";
+
+Structure specification is going to require the introduction of an
+object model in the language. The "." (dot) operator is going to be
+extended beyond the use as structure element access, but also allow
+for a object method call syntax similar to C++ and Java.
+
+ L1cacheMemory.cache_allocate(addr);
+
+Polymorphism
+------------
+
+We are also going to want to allow for polymorphism for many of the
+structures. We already have a limited degree of polymorphism between
+different protocols by using the same cache memory structure with
+different "CacheEntry" types in each protocol. Now that we are going
+to have multiple levels of cache, each requiring slightly different
+state bits, we are going to want to specify cache memory structures
+which have different "CacheEntry" types in the same protocol. To do
+this right, this is going to require adding full polymorphism support
+to the language. Right now we imagine something like C++'s templates,
+since they are a more natural fit to hardware synthesis in the future.
+
+Type Checker
+------------
+
+All of the above substantially complicates our type system by
+requiring more types and scoping rules. As a step towards
+understanding the implications of the type system, a type checking
+system will be implemented. This is a hard requirement if we are ever
+to distribute the system since receiving compile time errors in the
+generated code is not acceptable. In order to ensure that we don't
+accidentally design a language that is not statically type checkable,
+it is important to add the type checker sooner rather than later.
+
+Event Triggering
+----------------
+
+In v0.2, PSM events were individually specified as sets of conditions.
+The following SLICC v0.2 code is a simplified example from the origin
+protocol.
+
+ event(Dir_data_ack_0, "Data ack 0", desc="... ack count == 0") {
+ if (queue_ready(responseNetwork)) {
+ peek(responseNetwork, ResponseMsg) {
+ if(in_msg.NumPendingAcks == 0) {
+ trigger(in_msg.Address);
+ }
+ }
+ }
+ }
+
+ event(Dir_data_ack_not_0, "Data ack not 0", desc="... ack count != 0") {
+ if (queue_ready(responseNetwork)) {
+ peek(responseNetwork, ResponseMsg) {
+ if(in_msg.NumPendingAcks != 0) {
+ trigger(in_msg.Address);
+ }
+ }
+ }
+ }
+
+The above code defines the exact conditions for the events to be
+triggered. This type of event specification led to redundant code and
+numerous bugs where conditions for different events were not
+completely orthogonal.
+
+In v0.3, events will be declared with no accompanying code (similar to
+how states are specified). Instead, the code that determines which
+event is triggered will be part of each incoming port's declaration.
+This approach should eliminate redundancy and bugs in trigger
+conditions. The v0.3 code for the above would look like:
+
+ event(Dir_data_ack_0, "Data ack 0", desc="... ack count = 0");
+ event(Dir_data_ack_not_0, "Data ack not 0", desc="... ack count != 0");
+
+ in_port(responseNetwork, ResponseMsg, "Response Network", desc="...") {
+ if(in_msg.NumPendingAcks == 0) {
+ trigger(Dir_data_ack_0, in_msg.Address);
+ } else {
+ trigger(Dir_data_ack_not_0, in_msg.Address);
+ }
+ }
+
+Notice that one no longer needs to explicitly check if the queue is
+ready or to perform the peek operation.
+
+Also notice that the type of messages that arrives on the port is
+explicitly declared. All ports, incoming and outgoing, are now
+explicitly type channels. You will still be required to include the
+type of message when manipulating the queue. The type specified will
+be statically type checked and also acts as self-documenting code.
+
+Other Improvements
+------------------
+
+There will be a number of other improvements in v0.3 such as general
+performance tuning and clean up of the internals of the compiler. The
+compiler will be modified to operate on multiple files. In addition,
+the abstract syntax tree internal to the code will need to be extended
+to encompass more information, including information parsed in from
+multiple files.
+
+The affiliates talk and the document for the language should also be
+updated to reflect the changes in the new version.
+
+Looking Forward
+---------------
+
+When designing v0.3 we are keeping future plans in mind.
+
+- When our designs of the multilevel cache hierarchy are complete, we
+ expect to have a large amount of replication between the protocols
+ and caches controllers within a protocol. For v0.4 we hope to look
+ at the patterns that have evolved and look for ways in which the
+ language can capture these patterns. Exploiting reuse will provide
+ quicker protocol development and maintainability.
+
+- By keeping the specification structural, we are looking towards
+ generating VHDL/Verilog from SLICC. The type system will help this,
+ as will more explicit instantiation and declaration of types and
+ structures. The structures now written in C++ (sequencer, network,
+ cache arrays) will be ported to the HDL we select. The rest of the
+ controllers will be generated by the compiler. At first the
+ generated controller will not be optimized. I believe that with
+ more effort we can automatically generate reasonably optimized,
+ pipelined implementation of the controllers.
+
+Implementation Plan
+-------------------
+
+- HTML generator
+- Extend internal parser AST nodes
+- Add get_state function and set_state procedure declarations
+- Move trigger logic from events to in_ports
+- Types
+ - Change type declaration syntax
+ - Declare primitive types and corresponding C++ types
+ - Add default values to structures and types
+ - Add object method call syntax
+ - Write type checker
+- Documentation
+ - Revise document
+ - Update presentation
+
+Document History
+----------------
+
+$Id: SLICC_V03.txt,v 3.0 2000/09/12 20:27:59 sorin Exp $
+
+$Log: SLICC_V03.txt,v $
+Revision 3.0 2000/09/12 20:27:59 sorin
+Version 3.0 signifies a checkpoint of the source tree right after the
+final draft of the ASPLOS '00 paper.
+
+Revision 1.1.1.1 2000/03/09 10:18:38 milo
+Initial import
+
+Revision 2.0 2000/01/19 07:21:13 milo
+Version 2.0
+
+Revision 1.5 2000/01/18 10:26:24 milo
+Changed the SLICC parser so that it generates a full AST. This is the
+first step in moving towards v0.3
+
+Revision 1.4 2000/01/17 18:36:15 sorin
+*** empty log message ***
+
+Revision 1.3 2000/01/15 10:30:16 milo
+Added implementation list
+
+Revision 1.2 2000/01/15 08:11:44 milo
+Minor revisions
+
+Revision 1.1 2000/01/15 07:14:17 milo
+Converted Dan's first draft into a text file. Significant
+modifications were made.
+
diff --git a/src/mem/slicc/doc/tutorial.tex b/src/mem/slicc/doc/tutorial.tex
new file mode 100644
index 000000000..c20dba156
--- /dev/null
+++ b/src/mem/slicc/doc/tutorial.tex
@@ -0,0 +1,574 @@
+%& latex
+\documentclass[11pt]{article}
+\usepackage{graphics}
+\usepackage{color}
+
+\textheight 9.0 in
+\topmargin -0.5 in
+\textwidth 6.5 in
+\oddsidemargin -0.0 in
+\evensidemargin -0.0 in
+
+\begin{document}
+
+\definecolor{dark}{gray}{0.5}
+
+\newcommand{\syntax}[1]{%
+\begin{center}
+\fbox{\tt \small
+\begin{tabular}{l}
+#1\end{tabular}}\end{center}}
+
+\begin{center}
+{\LARGE Tutorial for SLICC v0.2} \\
+\vspace{.25in}
+{\large Milo Martin} \\
+{\large 8/25/1999}
+\end{center}
+
+\section*{Overview}
+
+This document attempts to illustrate the syntax and expressiveness of
+the cache coherence protocol specification language through a small
+example. A ``stupido'' cache coherence protocol is described in prose
+and then expressed in the language.
+
+The protocol used as the running example is described. Then each of
+the elements of the protocol is discussed and expressed in the
+language: states, events, transitions, and actions.
+
+\section*{Protocol Description}
+
+In order to make this example a simple as possible, the protocol
+described is a simple as possible and makes many simplifying
+assumptions. These simplifications were made only to clarify the
+exposition and are not indications of limitations of the
+expressiveness of the description language. We have already specified
+a more complicated MSI broadcast snooping protocol, a multicast
+snooping protocol, and a directory protocol. The simplifying
+assumptions are listed below. The remaining details of the protocol
+are described in the sections where we give the syntax of the
+language.
+
+\begin{itemize}
+
+\item
+The protocol uses broadcast snooping that assumes that a broadcast can
+only occur if all processors have processed all of their incoming
+address transactions. In essence, when a processor issue an address
+request, that request will be next in the global order. This allows
+us to avoid needed to handle the cases before we have observed our
+request in the global order.
+
+\item
+The protocol has only Modified and Idle stable states. (Note: Even
+the Shared state is omitted.)
+
+\item
+To avoid describing replacement (PutX's) and writebacks, the caches
+are in treated as infinite in size.
+
+\item
+No forward progress bit is used, so the protocol as specified does not
+guarantee forward progress.
+
+\item
+Only the mandatory request queue is used. No optional or prefetch
+queue is described.
+
+\item
+The above simplifications reduce the need for TBEs (Translation Buffer
+Entries) and thus the idea of a TBE is not include.
+
+\item
+Each memory module is assumed to have some state associated with each
+cache block in the memory. This requires a simple directory/memory
+state machine to work as a compliment to the processor state machine.
+Traditional broadcast snooping protocols often have no ``directory''
+state in the memory.
+
+\end{itemize}
+
+\section*{Protocol Messages}
+
+Cache coherence protocols communicate by sending well defined
+messages. To fully specify a cache coherence protocol we need to be
+able to specify the message types and fields. For this protocol we
+have address messages ({\tt AddressMsg}) which are broadcast, and data
+messages ({\tt DataMsg}) which are point-to-point. Address messages
+have an address field ({\tt Address}), a request type ({\tt Type}),
+and which processor made the request ({\tt Requestor}). Data message
+have an address field ({\tt Address}), a destination ({\tt
+Destination}), and the actual cache block being transfered ({\tt
+DataBlk}). The names in parenthesis are important because those are
+the names which code later in the specification will reference various
+message types and fields in the messages.
+
+Messages are declared by creating types with {\tt new\_type()} and
+adding fields with {\tt type\_field()}. The exact syntax for
+declaring types and message is a bit ugly right now and is going to be
+changed in the near future. If you wish, please see the appendix for
+an example of the current syntax.
+
+
+
+\section*{Cache States}
+
+Idle and Modified are the two stable states in our protocol. In
+addition the we have a single transient processor state. This state
+is used after a processor has issued a request and is waiting for the
+data response to arrive.
+
+Declaring states in the language is the first of a number of
+declarations we will be using. All of these declarations have a
+similar format. Below is the format for a state declaration.
+
+\syntax{
+{\tt state({\em identifier}, {\em shorthand}, {\em pair1}, {\em pair2}, ...);}
+}
+
+{\em identifier} is a name that is used later to
+refer to this state later in the description. It must start with a
+letter and after than can have any combination of letters, numbers,
+and the underscore character. {\em shorthand} is a quoted string
+which contains the shorthand that should be used for the state when
+generating tables and such.
+
+The {\em pair}'s are used to associate arbitrary information with each
+state. Zero or more pairs can be included in each declaration. For
+example we want to have a more verbose description of each state when
+we generate the table which contains the states and descriptions.
+This information is encoded in the language by adding a {\tt desc}
+parameter to a declaration. The name of the parameter is followed by
+an equal sign and a string with the description. The {\tt desc} pair
+technically optional, however the table generation tool will complain
+about a missing description if it is not present.
+
+The three states for our protocol are expressed as follows:
+
+\begin{verbatim}
+state(I, "I", desc="Idle");
+state(M, "M", desc="Modified");
+state(IM, "IM", desc="Idle, issued request but have not seen data yet");
+\end{verbatim}
+
+\section*{Cache Events}
+
+Events are external stimulus that cause the state machine to take
+action. This is most often a message in one of the queues from the
+network or processor. Events form the columns of the protocol table.
+Our simple protocol has one event per incoming queue. When a message
+is waiting in one of these queues and event can occur. We can see a
+request from the processor in the mandatory queue, another processor's
+request, or a data response.
+
+Events are declared in the language similarly to states. The {\em
+identifier}, {\em shorthand}, and {\em pair}'s have the same purpose
+as in a state declaration.
+
+\syntax{
+event({\em identifier}, {\em shorthand}, {\em pair1}, {\em pair2}, ...) \{ \\
+\hspace{.1in} {\em statement\_list} \\
+\} \\
+}
+
+Events are different in that they have a list of statements which
+allows exact specification of when the event should ``trigger'' a
+transition. These statements are mini-programming language with
+syntax similar to that of C. For example the {\tt peek} construct in
+this context checks to see if there is a message at the head of the
+specified queue, and if so, conceptually copies the message to a
+temporary variable accessed as {\tt in\_msg}. The language also
+supports various procedure calls, functions, conditional statements,
+assignment, and queue operations such as peek, enqueue and dequeue.
+The {\tt trigger()} construct takes an address as the only parameter.
+This is the address that should be triggered for the event. To give
+you a feel for what this code looks like, the three events for our
+simple protocol are below.
+
+\begin{verbatim}
+event(LoadStore, "LoadStore", desc="Load or Store request from local processor") {
+ peek(mandatoryQueue_ptr, CacheMsg) {
+ trigger(in_msg.Address);
+ }
+}
+
+event(Other_GETX, "Other GETX", desc="Observed a GETX request from another processor") {
+ peek(addressNetwork_ptr, AddressMsg) {
+ if (in_msg.Requestor != id) {
+ trigger(in_msg.Address);
+ }
+ }
+}
+
+event(Data, "Data", desc="Data for this block from the data network") {
+ peek(dataNetwork_ptr, DataMsg) {
+ trigger(in_msg.Address);
+ }
+}
+\end{verbatim}
+
+\section*{Cache Actions}
+
+Actions are the privative operations that are performed by various
+state transitions. These correspond (by convention) to the lower case
+letters in the tables. We need several actions in our protocol
+including issuing a GetX request, servicing a cache hit, send data
+from the cache to the requestor, writing data into the cache, and
+popping the various queues.
+
+The syntax of an action declaration is similar to an event
+declaration. The difference is that statements in the statement list
+are used to implement the desired action, and not triggering an event.
+
+\syntax{action({\em identifier}, {\em shorthand}, {\em pair1}, {\em pair2}, ...) \{ \\
+\hspace{.1in} {\em statement\_list} \\
+\}
+}
+
+The actions for this protocol use more of the features of the
+language. Some of the interesting case are discussed below.
+
+\begin{itemize}
+
+\item
+To manipulate values we need assignment statements (notice the use of
+{\verb+:=+} as the assignment operator). The action to write data
+into the cache looks at the incoming data message and puts the data in
+the cache. Notice the use of square brackets to lookup the block in
+the cache based on the address of the block.
+
+\begin{verbatim}
+action(w_writeDataToCache, "w", desc="Write data from data message into cache") {
+ peek(dataNetwork_ptr, DataMsg) {
+ cacheMemory_ptr[address].DataBlk := in_msg.DataBlk;
+ }
+}
+\end{verbatim}
+
+\item
+In addition to peeking at queues, we also enqueue messages. The {\tt
+enqueue} construct works similarly to the {\tt peek} construct. {\tt
+enqueue} creates a temporary called {\tt out\_msg}. You can assign
+the fields of this message. At the end of the {\tt enqueue} construct
+the message is implicitly inserted in the outgoing queue of the
+specified network. Notice also how the type of the message is
+specified and how the assignment statements use the names of the
+fields of the messages. {\tt address} is the address for which the
+event was {\tt trigger}ed.
+
+\begin{verbatim}
+action(g_issueGETX, "g", desc="Issue GETX.") {
+ enqueue(addressNetwork_ptr, AddressMsg) {
+ out_msg.Address := address;
+ out_msg.Type := "GETX";
+ out_msg.Requestor := id;
+ }
+}
+\end{verbatim}
+
+\item
+Some times we need to use both {\tt peek} and {\tt enqueue} together.
+In this example we look at an incoming address request to figure out
+who to whom to forward the data value.
+
+\begin{verbatim}
+action(r_cacheToRequestor, "r", desc="Send data from the cache to the requestor") {
+ peek(addressNetwork_ptr, AddressMsg) {
+ enqueue(dataNetwork_ptr, DataMsg) {
+ out_msg.Address := address;
+ out_msg.Destination := in_msg.Requestor;
+ out_msg.DataBlk := cacheMemory_ptr[address].DataBlk;
+ }
+ }
+}
+\end{verbatim}
+
+\item
+We also need to pop the various queues.
+\begin{verbatim}
+action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") {
+ dequeue(mandatoryQueue_ptr);
+}
+\end{verbatim}
+
+\item
+Finally we have the ability to call procedures and functions. The
+following is an example of a procedure call. Currently all of the
+procedures and functions are used to handle all of the more specific
+operations. These are currently hard coded into the generator.
+
+\begin{verbatim}
+action(h_hit, "h", desc="Service load/store from the cache.") {
+ serviceLdSt(address, cacheMemory_ptr[address].DataBlk);
+}
+\end{verbatim}
+
+\end{itemize}
+
+\section*{Cache Transitions}
+
+The cross product of states and events gives us the set of possible
+transitions. For example, for our example protocol the empty would
+be:
+
+\begin{center}
+\begin{tabular}{|l||l|l|l|} \hline
+ & LoadStore & Other GETX & Data \\ \hline \hline
+I & & & \\ \hline
+M & & & \\ \hline
+IM & & & \\ \hline
+\end{tabular}
+\end{center}
+
+
+Transitions are atomic and are the heart of the protocol
+specification. The transition specifies both what the next state, and
+also what actions are performed for each unique state/event pair. The
+transition declaration looks different from the other declarations:
+
+\syntax{
+transition({\em state}, {\em event}, {\em new\_state}, {\em pair1}, {\em pair2}, ...) \{ \\
+\hspace{.1in} {\em action\_identifier\_list}\\
+\}
+}
+
+{\em state} and {\em event} are the pair which uniquely identifies the
+transition. {\em state} correspond to the row where {\em event}
+selects the column. {\em new\_state} is an optional parameter. If
+{\em new\_state} is specified, that is the state when the atomic
+transition is completed. If the parameter is omitted there is assumed
+to be no state change. An impossible transition is specified by
+simply not declaring an event for that state/event pair.
+
+We also place list of actions in the curly braces. The {\em
+action\_identifier}'s correspond to the identifier specified as the
+first parameter of an action declaration. The action list is a list
+of operations to be performed when this transition occurs. The
+actions also knows what preconditions are necessary are required for
+the action to be performed. For example a necessary precondition for
+an action which sends a message is that there is a space available in
+the outgoing queue. Each transition is considered atomic, and thus
+the generated code ensures that all of the actions can be completed
+before performing and of the actions.
+
+In our running example protocol it is only possible to receive data in
+the {\em IM} state. The other seven cases can occur and are declared
+as follows. Below are a couple of examples. See the appendix for a
+complete list.
+
+\newpage
+\begin{verbatim}
+transition(I, LoadStore, IM) {
+ g_issueGETX;
+}
+
+transition(M, LoadStore) {
+ h_hit;
+ k_popMandatoryQueue;
+}
+
+transition(M, Other_GETX, I) {
+ r_cacheToRequestor;
+ i_popAddressQueue;
+}
+\end{verbatim}
+
+From the above declarations we can generate a table. Each box can
+have lower case letters which corresponds to the list of actions
+possibly followed by a slash and a state (in uppercase letters). If
+there is no slash and state, the transition does not change the state.
+
+\begin{center}
+\begin{tabular}{|l||l|l|l|} \hline
+ & LoadStore & Other GETX & Data \\ \hline \hline
+I & g/IM & i & (impossible)\\ \hline
+M & hk & ri/I & (impossible)\\ \hline
+IM & z & z & wj/M \\ \hline
+\end{tabular}
+\end{center}
+
+There is a useful shorthand for specifying many transitions with the
+same action. One or both of {\em event} and {\em state} can be a list
+in curly braces. This defines the cross product of the sets in one
+declaration. If no {\em new\_state} is specified none of the
+transitions cause a state change. If {\em new\_state} is specified,
+all of the transitions in the cross product of the sets has the same
+next state. For example, in the below transitions both IM/LoadStore
+and IM/Other\_GETX have the action {\tt z\_delayTrans}.
+\begin{verbatim}
+transition(IM, LoadStore) {
+ z_delayTrans;
+}
+
+transition(IM, Other_GETX) {
+ z_delayTrans;
+}
+\end{verbatim}
+These can be specified in a single declaration:
+\begin{verbatim}
+transition(IM, {LoadStore, Other_GETX}) {
+ z_delayTrans;
+}
+\end{verbatim}
+
+
+\newpage
+\section*{Appendix - Sample Cache Controller Specification}
+
+{\small
+\begin{verbatim}
+machine(processor, "Simple MI Processor") {
+
+ // AddressMsg
+ new_type(AddressMsg, "AddressMsg", message="yes", desc="");
+ type_field(AddressMsg, Address, "address",
+ desc="Physical address for this request",
+ c_type=PhysAddress, c_include="Address.hh", murphi_type="");
+ type_field(AddressMsg, Type, "type",
+ desc="Type of request (GetS, GetX, PutX, etc)",
+ c_type=CoherenceRequestType, c_include="CoherenceRequestType.hh", murphi_type="");
+ type_field(AddressMsg, Requestor, "requestor",
+ desc="Node who initiated the request",
+ c_type=ComponentID, c_include="ComponentID.hh", murphi_type="");
+
+ // DataMsg
+ new_type(DataMsg, "DataMsg", message="yes", desc="");
+ type_field(DataMsg, Address, "address",
+ desc="Physical address for this request",
+ c_type=PhysAddress, c_include="Address.hh", murphi_type="");
+ type_field(DataMsg, Destination, "destination",
+ desc="Node to whom the data is sent",
+ c_type=Set, c_include="Set.hh", murphi_type="");
+ type_field(DataMsg, DataBlk, "data",
+ desc="Node to whom the data is sent",
+ c_type=DataBlock, c_include="DataBlock.hh", murphi_type="");
+
+ // CacheEntry
+ new_type(CacheEntry, "CacheEntry");
+ type_field(CacheEntry, CacheState, "Cache state", desc="cache state",
+ c_type=CacheState, c_include="CacheState.hh", murphi_type="");
+ type_field(CacheEntry, DataBlk, "data", desc="data for the block",
+ c_type=DataBlock, c_include="DataBlock.hh", murphi_type="");
+
+ // DirectoryEntry
+ new_type(DirectoryEntry, "DirectoryEntry");
+ type_field(DirectoryEntry, DirectoryState, "Directory state", desc="Directory state",
+ c_type=DirectoryState, c_include="DirectoryState.hh", murphi_type="");
+ type_field(DirectoryEntry, DataBlk, "data", desc="data for the block",
+ c_type=DataBlock, c_include="DataBlock.hh", murphi_type="");
+
+\end{verbatim}
+\newpage
+\begin{verbatim}
+ // STATES
+ state(I, "I", desc="Idle");
+ state(M, "M", desc="Modified");
+ state(IM, "IM", desc="Idle, issued request but have not seen data yet");
+
+ // EVENTS
+
+ // From processor
+ event(LoadStore, "LoadStore", desc="Load or Store request from local processor") {
+ peek(mandatoryQueue_ptr, CacheMsg) {
+ trigger(in_msg.Address);
+ }
+ }
+
+ // From Address network
+ event(Other_GETX, "Other GETX", desc="Observed a GETX request from another processor") {
+ peek(addressNetwork_ptr, AddressMsg) {
+ if (in_msg.Requestor != id) {
+ trigger(in_msg.Address);
+ }
+ }
+ }
+
+ // From Data network
+ event(Data, "Data", desc="Data for this block from the data network") {
+ peek(dataNetwork_ptr, DataMsg) {
+ trigger(in_msg.Address);
+ }
+ }
+
+ // ACTIONS
+ action(g_issueGETX, "g", desc="Issue GETX.") {
+ enqueue(addressNetwork_ptr, AddressMsg) {
+ out_msg.Address := address;
+ out_msg.Type := "GETX";
+ out_msg.Requestor := id;
+ }
+ }
+
+ action(h_hit, "h", desc="Service load/store from the cache.") {
+ serviceLdSt(address, cacheMemory_ptr[address].DataBlk);
+ }
+
+ action(i_popAddressQueue, "i", desc="Pop incoming address queue.") {
+ dequeue(addressNetwork_ptr);
+ }
+
+ action(j_popDataQueue, "j", desc="Pop incoming data queue.") {
+ dequeue(dataNetwork_ptr);
+ }
+
+ action(k_popMandatoryQueue, "k", desc="Pop mandatory queue.") {
+ dequeue(mandatoryQueue_ptr);
+ }
+
+ action(r_cacheToRequestor, "r", desc="Send data from the cache to the requestor") {
+ peek(addressNetwork_ptr, AddressMsg) {
+ enqueue(dataNetwork_ptr, DataMsg) {
+ out_msg.Address := address;
+ out_msg.Destination := in_msg.Requestor;
+ out_msg.DataBlk := cacheMemory_ptr[address].DataBlk;
+ }
+ }
+ }
+
+ action(w_writeDataToCache, "w", desc="Write data from data message into cache") {
+ peek(dataNetwork_ptr, DataMsg) {
+ cacheMemory_ptr[address].DataBlk := in_msg.DataBlk;
+ }
+ }
+
+ action(z_delayTrans, "z", desc="Cannot be handled right now.") {
+ stall();
+ }
+
+ // TRANSITIONS
+
+ // Transitions from Idle
+ transition(I, LoadStore, IM) {
+ g_issueGETX;
+ }
+
+ transition(I, Other_GETX) {
+ i_popAddressQueue;
+ }
+
+ // Transitions from Modified
+ transition(M, LoadStore) {
+ h_hit;
+ k_popMandatoryQueue;
+ }
+
+ transition(M, Other_GETX, I) {
+ r_cacheToRequestor;
+ i_popAddressQueue;
+ }
+
+ // Transitions from IM
+ transition(IM, {LoadStore, Other_GETX}) {
+ z_delayTrans;
+ }
+
+ transition(IM, Data, M) {
+ w_writeDataToCache;
+ j_popDataQueue;
+ }
+}
+\end{verbatim}
+}
+\end{document}
+