diff options
Diffstat (limited to 'src/mem/slicc/doc')
-rw-r--r-- | src/mem/slicc/doc/SLICC_V03.txt | 307 | ||||
-rw-r--r-- | src/mem/slicc/doc/tutorial.tex | 574 |
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} + |