1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2# Copyright (c) 2009 The Hewlett-Packard Development Company 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28from m5.util import orderdict 29 30from slicc.symbols.Symbol import Symbol 31from slicc.symbols.Var import Var 32import slicc.generate.html as html 33import re 34 35python_class_map = { 36 "int": "Int", 37 "uint32_t" : "UInt32", 38 "std::string": "String", 39 "bool": "Bool", 40 "CacheMemory": "RubyCache", 41 "WireBuffer": "RubyWireBuffer", 42 "Sequencer": "RubySequencer", 43 "DirectoryMemory": "RubyDirectoryMemory", 44 "MemoryControl": "MemoryControl", 45 "DMASequencer": "DMASequencer", 46 "Prefetcher":"Prefetcher", 47 "Cycles":"Cycles", 48 } 49 50class StateMachine(Symbol): 51 def __init__(self, symtab, ident, location, pairs, config_parameters): 52 super(StateMachine, self).__init__(symtab, ident, location, pairs) 53 self.table = None 54 self.config_parameters = config_parameters 55 self.prefetchers = [] 56 57 for param in config_parameters: 58 if param.pointer:
| 1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2# Copyright (c) 2009 The Hewlett-Packard Development Company 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28from m5.util import orderdict 29 30from slicc.symbols.Symbol import Symbol 31from slicc.symbols.Var import Var 32import slicc.generate.html as html 33import re 34 35python_class_map = { 36 "int": "Int", 37 "uint32_t" : "UInt32", 38 "std::string": "String", 39 "bool": "Bool", 40 "CacheMemory": "RubyCache", 41 "WireBuffer": "RubyWireBuffer", 42 "Sequencer": "RubySequencer", 43 "DirectoryMemory": "RubyDirectoryMemory", 44 "MemoryControl": "MemoryControl", 45 "DMASequencer": "DMASequencer", 46 "Prefetcher":"Prefetcher", 47 "Cycles":"Cycles", 48 } 49 50class StateMachine(Symbol): 51 def __init__(self, symtab, ident, location, pairs, config_parameters): 52 super(StateMachine, self).__init__(symtab, ident, location, pairs) 53 self.table = None 54 self.config_parameters = config_parameters 55 self.prefetchers = [] 56 57 for param in config_parameters: 58 if param.pointer:
|
685 686 code(''' 687 688void 689$c_ident::regStats() 690{ 691 AbstractController::regStats(); 692 693 if (m_version == 0) { 694 for (${ident}_Event event = ${ident}_Event_FIRST; 695 event < ${ident}_Event_NUM; ++event) { 696 Stats::Vector *t = new Stats::Vector(); 697 t->init(m_num_controllers); 698 t->name(g_system_ptr->name() + ".${c_ident}." + 699 ${ident}_Event_to_string(event)); 700 t->flags(Stats::pdf | Stats::total | Stats::oneline | 701 Stats::nozero); 702 703 eventVec.push_back(t); 704 } 705 706 for (${ident}_State state = ${ident}_State_FIRST; 707 state < ${ident}_State_NUM; ++state) { 708 709 transVec.push_back(std::vector<Stats::Vector *>()); 710 711 for (${ident}_Event event = ${ident}_Event_FIRST; 712 event < ${ident}_Event_NUM; ++event) { 713 714 Stats::Vector *t = new Stats::Vector(); 715 t->init(m_num_controllers); 716 t->name(g_system_ptr->name() + ".${c_ident}." + 717 ${ident}_State_to_string(state) + 718 "." + ${ident}_Event_to_string(event)); 719 720 t->flags(Stats::pdf | Stats::total | Stats::oneline | 721 Stats::nozero); 722 transVec[state].push_back(t); 723 } 724 } 725 } 726} 727 728void 729$c_ident::collateStats() 730{ 731 for (${ident}_Event event = ${ident}_Event_FIRST; 732 event < ${ident}_Event_NUM; ++event) { 733 for (unsigned int i = 0; i < m_num_controllers; ++i) { 734 std::map<uint32_t, AbstractController *>::iterator it = 735 g_abs_controls[MachineType_${ident}].find(i); 736 assert(it != g_abs_controls[MachineType_${ident}].end()); 737 (*eventVec[event])[i] = 738 (($c_ident *)(*it).second)->getEventCount(event); 739 } 740 } 741 742 for (${ident}_State state = ${ident}_State_FIRST; 743 state < ${ident}_State_NUM; ++state) { 744 745 for (${ident}_Event event = ${ident}_Event_FIRST; 746 event < ${ident}_Event_NUM; ++event) { 747 748 for (unsigned int i = 0; i < m_num_controllers; ++i) { 749 std::map<uint32_t, AbstractController *>::iterator it = 750 g_abs_controls[MachineType_${ident}].find(i); 751 assert(it != g_abs_controls[MachineType_${ident}].end()); 752 (*transVec[state][event])[i] = 753 (($c_ident *)(*it).second)->getTransitionCount(state, event); 754 } 755 } 756 } 757} 758 759void 760$c_ident::countTransition(${ident}_State state, ${ident}_Event event) 761{ 762 assert(m_possible[state][event]); 763 m_counters[state][event]++; 764 m_event_counters[event]++; 765} 766void 767$c_ident::possibleTransition(${ident}_State state, 768 ${ident}_Event event) 769{ 770 m_possible[state][event] = true; 771} 772 773uint64 774$c_ident::getEventCount(${ident}_Event event) 775{ 776 return m_event_counters[event]; 777} 778 779bool 780$c_ident::isPossible(${ident}_State state, ${ident}_Event event) 781{ 782 return m_possible[state][event]; 783} 784 785uint64 786$c_ident::getTransitionCount(${ident}_State state, 787 ${ident}_Event event) 788{ 789 return m_counters[state][event]; 790} 791 792int 793$c_ident::getNumControllers() 794{ 795 return m_num_controllers; 796} 797 798MessageBuffer* 799$c_ident::getMandatoryQueue() const 800{ 801 return $mq_ident; 802} 803 804Sequencer* 805$c_ident::getSequencer() const 806{ 807 return $seq_ident; 808} 809 810void 811$c_ident::print(ostream& out) const 812{ 813 out << "[$c_ident " << m_version << "]"; 814} 815 816void $c_ident::resetStats() 817{ 818 for (int state = 0; state < ${ident}_State_NUM; state++) { 819 for (int event = 0; event < ${ident}_Event_NUM; event++) { 820 m_counters[state][event] = 0; 821 } 822 } 823 824 for (int event = 0; event < ${ident}_Event_NUM; event++) { 825 m_event_counters[event] = 0; 826 } 827 828 AbstractController::resetStats(); 829} 830''') 831 832 if self.EntryType != None: 833 code(''' 834 835// Set and Reset for cache_entry variable 836void 837$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 838{ 839 m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 840} 841 842void 843$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 844{ 845 m_cache_entry_ptr = 0; 846} 847''') 848 849 if self.TBEType != None: 850 code(''' 851 852// Set and Reset for tbe variable 853void 854$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 855{ 856 m_tbe_ptr = m_new_tbe; 857} 858 859void 860$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 861{ 862 m_tbe_ptr = NULL; 863} 864''') 865 866 code(''' 867 868void 869$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) 870{ 871''') 872 # 873 # Record cache contents for all associated caches. 874 # 875 code.indent() 876 for param in self.config_parameters: 877 if param.type_ast.type.ident == "CacheMemory": 878 assert(param.pointer) 879 code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') 880 881 code.dedent() 882 code(''' 883} 884 885// Actions 886''') 887 if self.TBEType != None and self.EntryType != None: 888 for action in self.actions.itervalues(): 889 if "c_code" not in action: 890 continue 891 892 code(''' 893/** \\brief ${{action.desc}} */ 894void 895$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 896{ 897 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 898 ${{action["c_code"]}} 899} 900 901''') 902 elif self.TBEType != None: 903 for action in self.actions.itervalues(): 904 if "c_code" not in action: 905 continue 906 907 code(''' 908/** \\brief ${{action.desc}} */ 909void 910$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) 911{ 912 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 913 ${{action["c_code"]}} 914} 915 916''') 917 elif self.EntryType != None: 918 for action in self.actions.itervalues(): 919 if "c_code" not in action: 920 continue 921 922 code(''' 923/** \\brief ${{action.desc}} */ 924void 925$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 926{ 927 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 928 ${{action["c_code"]}} 929} 930 931''') 932 else: 933 for action in self.actions.itervalues(): 934 if "c_code" not in action: 935 continue 936 937 code(''' 938/** \\brief ${{action.desc}} */ 939void 940$c_ident::${{action.ident}}(const Address& addr) 941{ 942 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 943 ${{action["c_code"]}} 944} 945 946''') 947 for func in self.functions: 948 code(func.generateCode()) 949 950 # Function for functional reads from messages buffered in the controller 951 code(''' 952bool 953$c_ident::functionalReadBuffers(PacketPtr& pkt) 954{ 955''') 956 for var in self.objects: 957 vtype = var.type 958 if vtype.isBuffer: 959 vid = "m_%s_ptr" % var.ident 960 code('if ($vid->functionalRead(pkt)) { return true; }') 961 code(''' 962 return false; 963} 964''') 965 966 # Function for functional writes to messages buffered in the controller 967 code(''' 968uint32_t 969$c_ident::functionalWriteBuffers(PacketPtr& pkt) 970{ 971 uint32_t num_functional_writes = 0; 972''') 973 for var in self.objects: 974 vtype = var.type 975 if vtype.isBuffer: 976 vid = "m_%s_ptr" % var.ident 977 code('num_functional_writes += $vid->functionalWrite(pkt);') 978 code(''' 979 return num_functional_writes; 980} 981''') 982 983 # Check if this controller has a peer, if yes then write the 984 # function for connecting to the peer. 985 if has_peer: 986 code(''' 987 988void 989$c_ident::getQueuesFromPeer(AbstractController *peer) 990{ 991''') 992 for var in self.objects: 993 if "network" in var and "physical_network" in var and \ 994 var["network"] == "From": 995 code(''' 996m_${{var.ident}}_ptr = peer->getPeerQueue(${{var["physical_network"]}}); 997assert(m_${{var.ident}}_ptr != NULL); 998m_${{var.ident}}_ptr->setReceiver(this); 999 1000''') 1001 code('}') 1002 1003 code.write(path, "%s.cc" % c_ident) 1004 1005 def printCWakeup(self, path, includes): 1006 '''Output the wakeup loop for the events''' 1007 1008 code = self.symtab.codeFormatter() 1009 ident = self.ident 1010 1011 outputRequest_types = True 1012 if len(self.request_types) == 0: 1013 outputRequest_types = False 1014 1015 code(''' 1016// Auto generated C++ code started by $__file__:$__line__ 1017// ${ident}: ${{self.short}} 1018 1019#include <sys/types.h> 1020#include <unistd.h> 1021 1022#include <cassert> 1023 1024#include "base/misc.hh" 1025#include "debug/RubySlicc.hh" 1026#include "mem/protocol/${ident}_Controller.hh" 1027#include "mem/protocol/${ident}_Event.hh" 1028#include "mem/protocol/${ident}_State.hh" 1029''') 1030 1031 if outputRequest_types: 1032 code('''#include "mem/protocol/${ident}_RequestType.hh"''') 1033 1034 code(''' 1035#include "mem/protocol/Types.hh" 1036#include "mem/ruby/common/Global.hh" 1037#include "mem/ruby/system/System.hh" 1038''') 1039 1040 1041 for include_path in includes: 1042 code('#include "${{include_path}}"') 1043 1044 code(''' 1045 1046using namespace std; 1047 1048void 1049${ident}_Controller::wakeup() 1050{ 1051 int counter = 0; 1052 while (true) { 1053 // Some cases will put us into an infinite loop without this limit 1054 assert(counter <= m_transitions_per_cycle); 1055 if (counter == m_transitions_per_cycle) { 1056 // Count how often we are fully utilized 1057 m_fully_busy_cycles++; 1058 1059 // Wakeup in another cycle and try again 1060 scheduleEvent(Cycles(1)); 1061 break; 1062 } 1063''') 1064 1065 code.indent() 1066 code.indent() 1067 1068 # InPorts 1069 # 1070 for port in self.in_ports: 1071 code.indent() 1072 code('// ${ident}InPort $port') 1073 if port.pairs.has_key("rank"): 1074 code('m_cur_in_port = ${{port.pairs["rank"]}};') 1075 else: 1076 code('m_cur_in_port = 0;') 1077 code('${{port["c_code_in_port"]}}') 1078 code.dedent() 1079 1080 code('') 1081 1082 code.dedent() 1083 code.dedent() 1084 code(''' 1085 break; // If we got this far, we have nothing left todo 1086 } 1087} 1088''') 1089 1090 code.write(path, "%s_Wakeup.cc" % self.ident) 1091 1092 def printCSwitch(self, path): 1093 '''Output switch statement for transition table''' 1094 1095 code = self.symtab.codeFormatter() 1096 ident = self.ident 1097 1098 code(''' 1099// Auto generated C++ code started by $__file__:$__line__ 1100// ${ident}: ${{self.short}} 1101 1102#include <cassert> 1103 1104#include "base/misc.hh" 1105#include "base/trace.hh" 1106#include "debug/ProtocolTrace.hh" 1107#include "debug/RubyGenerated.hh" 1108#include "mem/protocol/${ident}_Controller.hh" 1109#include "mem/protocol/${ident}_Event.hh" 1110#include "mem/protocol/${ident}_State.hh" 1111#include "mem/protocol/Types.hh" 1112#include "mem/ruby/common/Global.hh" 1113#include "mem/ruby/system/System.hh" 1114 1115#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 1116 1117#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 1118#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 1119 1120TransitionResult 1121${ident}_Controller::doTransition(${ident}_Event event, 1122''') 1123 if self.EntryType != None: 1124 code(''' 1125 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 1126''') 1127 if self.TBEType != None: 1128 code(''' 1129 ${{self.TBEType.c_ident}}* m_tbe_ptr, 1130''') 1131 code(''' 1132 const Address addr) 1133{ 1134''') 1135 code.indent() 1136 1137 if self.TBEType != None and self.EntryType != None: 1138 code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 1139 elif self.TBEType != None: 1140 code('${ident}_State state = getState(m_tbe_ptr, addr);') 1141 elif self.EntryType != None: 1142 code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 1143 else: 1144 code('${ident}_State state = getState(addr);') 1145 1146 code(''' 1147${ident}_State next_state = state; 1148 1149DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 1150 *this, curCycle(), ${ident}_State_to_string(state), 1151 ${ident}_Event_to_string(event), addr); 1152 1153TransitionResult result = 1154''') 1155 if self.TBEType != None and self.EntryType != None: 1156 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 1157 elif self.TBEType != None: 1158 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 1159 elif self.EntryType != None: 1160 code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 1161 else: 1162 code('doTransitionWorker(event, state, next_state, addr);') 1163 1164 code(''' 1165 1166if (result == TransitionResult_Valid) { 1167 DPRINTF(RubyGenerated, "next_state: %s\\n", 1168 ${ident}_State_to_string(next_state)); 1169 countTransition(state, event); 1170 1171 DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 1172 curTick(), m_version, "${ident}", 1173 ${ident}_Event_to_string(event), 1174 ${ident}_State_to_string(state), 1175 ${ident}_State_to_string(next_state), 1176 addr, GET_TRANSITION_COMMENT()); 1177 1178 CLEAR_TRANSITION_COMMENT(); 1179''') 1180 if self.TBEType != None and self.EntryType != None: 1181 code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 1182 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1183 elif self.TBEType != None: 1184 code('setState(m_tbe_ptr, addr, next_state);') 1185 code('setAccessPermission(addr, next_state);') 1186 elif self.EntryType != None: 1187 code('setState(m_cache_entry_ptr, addr, next_state);') 1188 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1189 else: 1190 code('setState(addr, next_state);') 1191 code('setAccessPermission(addr, next_state);') 1192 1193 code(''' 1194} else if (result == TransitionResult_ResourceStall) { 1195 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1196 curTick(), m_version, "${ident}", 1197 ${ident}_Event_to_string(event), 1198 ${ident}_State_to_string(state), 1199 ${ident}_State_to_string(next_state), 1200 addr, "Resource Stall"); 1201} else if (result == TransitionResult_ProtocolStall) { 1202 DPRINTF(RubyGenerated, "stalling\\n"); 1203 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1204 curTick(), m_version, "${ident}", 1205 ${ident}_Event_to_string(event), 1206 ${ident}_State_to_string(state), 1207 ${ident}_State_to_string(next_state), 1208 addr, "Protocol Stall"); 1209} 1210 1211return result; 1212''') 1213 code.dedent() 1214 code(''' 1215} 1216 1217TransitionResult 1218${ident}_Controller::doTransitionWorker(${ident}_Event event, 1219 ${ident}_State state, 1220 ${ident}_State& next_state, 1221''') 1222 1223 if self.TBEType != None: 1224 code(''' 1225 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1226''') 1227 if self.EntryType != None: 1228 code(''' 1229 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1230''') 1231 code(''' 1232 const Address& addr) 1233{ 1234 switch(HASH_FUN(state, event)) { 1235''') 1236 1237 # This map will allow suppress generating duplicate code 1238 cases = orderdict() 1239 1240 for trans in self.transitions: 1241 case_string = "%s_State_%s, %s_Event_%s" % \ 1242 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1243 1244 case = self.symtab.codeFormatter() 1245 # Only set next_state if it changes 1246 if trans.state != trans.nextState: 1247 ns_ident = trans.nextState.ident 1248 case('next_state = ${ident}_State_${ns_ident};') 1249 1250 actions = trans.actions 1251 request_types = trans.request_types 1252 1253 # Check for resources 1254 case_sorter = [] 1255 res = trans.resources 1256 for key,val in res.iteritems(): 1257 val = ''' 1258if (!%s.areNSlotsAvailable(%s)) 1259 return TransitionResult_ResourceStall; 1260''' % (key.code, val) 1261 case_sorter.append(val) 1262 1263 # Check all of the request_types for resource constraints 1264 for request_type in request_types: 1265 val = ''' 1266if (!checkResourceAvailable(%s_RequestType_%s, addr)) { 1267 return TransitionResult_ResourceStall; 1268} 1269''' % (self.ident, request_type.ident) 1270 case_sorter.append(val) 1271 1272 # Emit the code sequences in a sorted order. This makes the 1273 # output deterministic (without this the output order can vary 1274 # since Map's keys() on a vector of pointers is not deterministic 1275 for c in sorted(case_sorter): 1276 case("$c") 1277 1278 # Record access types for this transition 1279 for request_type in request_types: 1280 case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 1281 1282 # Figure out if we stall 1283 stall = False 1284 for action in actions: 1285 if action.ident == "z_stall": 1286 stall = True 1287 break 1288 1289 if stall: 1290 case('return TransitionResult_ProtocolStall;') 1291 else: 1292 if self.TBEType != None and self.EntryType != None: 1293 for action in actions: 1294 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1295 elif self.TBEType != None: 1296 for action in actions: 1297 case('${{action.ident}}(m_tbe_ptr, addr);') 1298 elif self.EntryType != None: 1299 for action in actions: 1300 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1301 else: 1302 for action in actions: 1303 case('${{action.ident}}(addr);') 1304 case('return TransitionResult_Valid;') 1305 1306 case = str(case) 1307 1308 # Look to see if this transition code is unique. 1309 if case not in cases: 1310 cases[case] = [] 1311 1312 cases[case].append(case_string) 1313 1314 # Walk through all of the unique code blocks and spit out the 1315 # corresponding case statement elements 1316 for case,transitions in cases.iteritems(): 1317 # Iterative over all the multiple transitions that share 1318 # the same code 1319 for trans in transitions: 1320 code(' case HASH_FUN($trans):') 1321 code(' $case\n') 1322 1323 code(''' 1324 default: 1325 fatal("Invalid transition\\n" 1326 "%s time: %d addr: %s event: %s state: %s\\n", 1327 name(), curCycle(), addr, event, state); 1328 } 1329 1330 return TransitionResult_Valid; 1331} 1332''') 1333 code.write(path, "%s_Transitions.cc" % self.ident) 1334 1335 1336 # ************************** 1337 # ******* HTML Files ******* 1338 # ************************** 1339 def frameRef(self, click_href, click_target, over_href, over_num, text): 1340 code = self.symtab.codeFormatter(fix_newlines=False) 1341 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1342 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1343 parent.frames[$over_num].location='$over_href' 1344 }\"> 1345 ${{html.formatShorthand(text)}} 1346 </A>""") 1347 return str(code) 1348 1349 def writeHTMLFiles(self, path): 1350 # Create table with no row hilighted 1351 self.printHTMLTransitions(path, None) 1352 1353 # Generate transition tables 1354 for state in self.states.itervalues(): 1355 self.printHTMLTransitions(path, state) 1356 1357 # Generate action descriptions 1358 for action in self.actions.itervalues(): 1359 name = "%s_action_%s.html" % (self.ident, action.ident) 1360 code = html.createSymbol(action, "Action") 1361 code.write(path, name) 1362 1363 # Generate state descriptions 1364 for state in self.states.itervalues(): 1365 name = "%s_State_%s.html" % (self.ident, state.ident) 1366 code = html.createSymbol(state, "State") 1367 code.write(path, name) 1368 1369 # Generate event descriptions 1370 for event in self.events.itervalues(): 1371 name = "%s_Event_%s.html" % (self.ident, event.ident) 1372 code = html.createSymbol(event, "Event") 1373 code.write(path, name) 1374 1375 def printHTMLTransitions(self, path, active_state): 1376 code = self.symtab.codeFormatter() 1377 1378 code(''' 1379<HTML> 1380<BODY link="blue" vlink="blue"> 1381 1382<H1 align="center">${{html.formatShorthand(self.short)}}: 1383''') 1384 code.indent() 1385 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1386 mid = machine.ident 1387 if i != 0: 1388 extra = " - " 1389 else: 1390 extra = "" 1391 if machine == self: 1392 code('$extra$mid') 1393 else: 1394 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1395 code.dedent() 1396 1397 code(""" 1398</H1> 1399 1400<TABLE border=1> 1401<TR> 1402 <TH> </TH> 1403""") 1404 1405 for event in self.events.itervalues(): 1406 href = "%s_Event_%s.html" % (self.ident, event.ident) 1407 ref = self.frameRef(href, "Status", href, "1", event.short) 1408 code('<TH bgcolor=white>$ref</TH>') 1409 1410 code('</TR>') 1411 # -- Body of table 1412 for state in self.states.itervalues(): 1413 # -- Each row 1414 if state == active_state: 1415 color = "yellow" 1416 else: 1417 color = "white" 1418 1419 click = "%s_table_%s.html" % (self.ident, state.ident) 1420 over = "%s_State_%s.html" % (self.ident, state.ident) 1421 text = html.formatShorthand(state.short) 1422 ref = self.frameRef(click, "Table", over, "1", state.short) 1423 code(''' 1424<TR> 1425 <TH bgcolor=$color>$ref</TH> 1426''') 1427 1428 # -- One column for each event 1429 for event in self.events.itervalues(): 1430 trans = self.table.get((state,event), None) 1431 if trans is None: 1432 # This is the no transition case 1433 if state == active_state: 1434 color = "#C0C000" 1435 else: 1436 color = "lightgrey" 1437 1438 code('<TD bgcolor=$color> </TD>') 1439 continue 1440 1441 next = trans.nextState 1442 stall_action = False 1443 1444 # -- Get the actions 1445 for action in trans.actions: 1446 if action.ident == "z_stall" or \ 1447 action.ident == "zz_recycleMandatoryQueue": 1448 stall_action = True 1449 1450 # -- Print out "actions/next-state" 1451 if stall_action: 1452 if state == active_state: 1453 color = "#C0C000" 1454 else: 1455 color = "lightgrey" 1456 1457 elif active_state and next.ident == active_state.ident: 1458 color = "aqua" 1459 elif state == active_state: 1460 color = "yellow" 1461 else: 1462 color = "white" 1463 1464 code('<TD bgcolor=$color>') 1465 for action in trans.actions: 1466 href = "%s_action_%s.html" % (self.ident, action.ident) 1467 ref = self.frameRef(href, "Status", href, "1", 1468 action.short) 1469 code(' $ref') 1470 if next != state: 1471 if trans.actions: 1472 code('/') 1473 click = "%s_table_%s.html" % (self.ident, next.ident) 1474 over = "%s_State_%s.html" % (self.ident, next.ident) 1475 ref = self.frameRef(click, "Table", over, "1", next.short) 1476 code("$ref") 1477 code("</TD>") 1478 1479 # -- Each row 1480 if state == active_state: 1481 color = "yellow" 1482 else: 1483 color = "white" 1484 1485 click = "%s_table_%s.html" % (self.ident, state.ident) 1486 over = "%s_State_%s.html" % (self.ident, state.ident) 1487 ref = self.frameRef(click, "Table", over, "1", state.short) 1488 code(''' 1489 <TH bgcolor=$color>$ref</TH> 1490</TR> 1491''') 1492 code(''' 1493<!- Column footer-> 1494<TR> 1495 <TH> </TH> 1496''') 1497 1498 for event in self.events.itervalues(): 1499 href = "%s_Event_%s.html" % (self.ident, event.ident) 1500 ref = self.frameRef(href, "Status", href, "1", event.short) 1501 code('<TH bgcolor=white>$ref</TH>') 1502 code(''' 1503</TR> 1504</TABLE> 1505</BODY></HTML> 1506''') 1507 1508 1509 if active_state: 1510 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1511 else: 1512 name = "%s_table.html" % self.ident 1513 code.write(path, name) 1514 1515__all__ = [ "StateMachine" ]
| 692 693 code(''' 694 695void 696$c_ident::regStats() 697{ 698 AbstractController::regStats(); 699 700 if (m_version == 0) { 701 for (${ident}_Event event = ${ident}_Event_FIRST; 702 event < ${ident}_Event_NUM; ++event) { 703 Stats::Vector *t = new Stats::Vector(); 704 t->init(m_num_controllers); 705 t->name(g_system_ptr->name() + ".${c_ident}." + 706 ${ident}_Event_to_string(event)); 707 t->flags(Stats::pdf | Stats::total | Stats::oneline | 708 Stats::nozero); 709 710 eventVec.push_back(t); 711 } 712 713 for (${ident}_State state = ${ident}_State_FIRST; 714 state < ${ident}_State_NUM; ++state) { 715 716 transVec.push_back(std::vector<Stats::Vector *>()); 717 718 for (${ident}_Event event = ${ident}_Event_FIRST; 719 event < ${ident}_Event_NUM; ++event) { 720 721 Stats::Vector *t = new Stats::Vector(); 722 t->init(m_num_controllers); 723 t->name(g_system_ptr->name() + ".${c_ident}." + 724 ${ident}_State_to_string(state) + 725 "." + ${ident}_Event_to_string(event)); 726 727 t->flags(Stats::pdf | Stats::total | Stats::oneline | 728 Stats::nozero); 729 transVec[state].push_back(t); 730 } 731 } 732 } 733} 734 735void 736$c_ident::collateStats() 737{ 738 for (${ident}_Event event = ${ident}_Event_FIRST; 739 event < ${ident}_Event_NUM; ++event) { 740 for (unsigned int i = 0; i < m_num_controllers; ++i) { 741 std::map<uint32_t, AbstractController *>::iterator it = 742 g_abs_controls[MachineType_${ident}].find(i); 743 assert(it != g_abs_controls[MachineType_${ident}].end()); 744 (*eventVec[event])[i] = 745 (($c_ident *)(*it).second)->getEventCount(event); 746 } 747 } 748 749 for (${ident}_State state = ${ident}_State_FIRST; 750 state < ${ident}_State_NUM; ++state) { 751 752 for (${ident}_Event event = ${ident}_Event_FIRST; 753 event < ${ident}_Event_NUM; ++event) { 754 755 for (unsigned int i = 0; i < m_num_controllers; ++i) { 756 std::map<uint32_t, AbstractController *>::iterator it = 757 g_abs_controls[MachineType_${ident}].find(i); 758 assert(it != g_abs_controls[MachineType_${ident}].end()); 759 (*transVec[state][event])[i] = 760 (($c_ident *)(*it).second)->getTransitionCount(state, event); 761 } 762 } 763 } 764} 765 766void 767$c_ident::countTransition(${ident}_State state, ${ident}_Event event) 768{ 769 assert(m_possible[state][event]); 770 m_counters[state][event]++; 771 m_event_counters[event]++; 772} 773void 774$c_ident::possibleTransition(${ident}_State state, 775 ${ident}_Event event) 776{ 777 m_possible[state][event] = true; 778} 779 780uint64 781$c_ident::getEventCount(${ident}_Event event) 782{ 783 return m_event_counters[event]; 784} 785 786bool 787$c_ident::isPossible(${ident}_State state, ${ident}_Event event) 788{ 789 return m_possible[state][event]; 790} 791 792uint64 793$c_ident::getTransitionCount(${ident}_State state, 794 ${ident}_Event event) 795{ 796 return m_counters[state][event]; 797} 798 799int 800$c_ident::getNumControllers() 801{ 802 return m_num_controllers; 803} 804 805MessageBuffer* 806$c_ident::getMandatoryQueue() const 807{ 808 return $mq_ident; 809} 810 811Sequencer* 812$c_ident::getSequencer() const 813{ 814 return $seq_ident; 815} 816 817void 818$c_ident::print(ostream& out) const 819{ 820 out << "[$c_ident " << m_version << "]"; 821} 822 823void $c_ident::resetStats() 824{ 825 for (int state = 0; state < ${ident}_State_NUM; state++) { 826 for (int event = 0; event < ${ident}_Event_NUM; event++) { 827 m_counters[state][event] = 0; 828 } 829 } 830 831 for (int event = 0; event < ${ident}_Event_NUM; event++) { 832 m_event_counters[event] = 0; 833 } 834 835 AbstractController::resetStats(); 836} 837''') 838 839 if self.EntryType != None: 840 code(''' 841 842// Set and Reset for cache_entry variable 843void 844$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 845{ 846 m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 847} 848 849void 850$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 851{ 852 m_cache_entry_ptr = 0; 853} 854''') 855 856 if self.TBEType != None: 857 code(''' 858 859// Set and Reset for tbe variable 860void 861$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 862{ 863 m_tbe_ptr = m_new_tbe; 864} 865 866void 867$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 868{ 869 m_tbe_ptr = NULL; 870} 871''') 872 873 code(''' 874 875void 876$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) 877{ 878''') 879 # 880 # Record cache contents for all associated caches. 881 # 882 code.indent() 883 for param in self.config_parameters: 884 if param.type_ast.type.ident == "CacheMemory": 885 assert(param.pointer) 886 code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') 887 888 code.dedent() 889 code(''' 890} 891 892// Actions 893''') 894 if self.TBEType != None and self.EntryType != None: 895 for action in self.actions.itervalues(): 896 if "c_code" not in action: 897 continue 898 899 code(''' 900/** \\brief ${{action.desc}} */ 901void 902$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 903{ 904 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 905 ${{action["c_code"]}} 906} 907 908''') 909 elif self.TBEType != None: 910 for action in self.actions.itervalues(): 911 if "c_code" not in action: 912 continue 913 914 code(''' 915/** \\brief ${{action.desc}} */ 916void 917$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) 918{ 919 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 920 ${{action["c_code"]}} 921} 922 923''') 924 elif self.EntryType != None: 925 for action in self.actions.itervalues(): 926 if "c_code" not in action: 927 continue 928 929 code(''' 930/** \\brief ${{action.desc}} */ 931void 932$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 933{ 934 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 935 ${{action["c_code"]}} 936} 937 938''') 939 else: 940 for action in self.actions.itervalues(): 941 if "c_code" not in action: 942 continue 943 944 code(''' 945/** \\brief ${{action.desc}} */ 946void 947$c_ident::${{action.ident}}(const Address& addr) 948{ 949 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 950 ${{action["c_code"]}} 951} 952 953''') 954 for func in self.functions: 955 code(func.generateCode()) 956 957 # Function for functional reads from messages buffered in the controller 958 code(''' 959bool 960$c_ident::functionalReadBuffers(PacketPtr& pkt) 961{ 962''') 963 for var in self.objects: 964 vtype = var.type 965 if vtype.isBuffer: 966 vid = "m_%s_ptr" % var.ident 967 code('if ($vid->functionalRead(pkt)) { return true; }') 968 code(''' 969 return false; 970} 971''') 972 973 # Function for functional writes to messages buffered in the controller 974 code(''' 975uint32_t 976$c_ident::functionalWriteBuffers(PacketPtr& pkt) 977{ 978 uint32_t num_functional_writes = 0; 979''') 980 for var in self.objects: 981 vtype = var.type 982 if vtype.isBuffer: 983 vid = "m_%s_ptr" % var.ident 984 code('num_functional_writes += $vid->functionalWrite(pkt);') 985 code(''' 986 return num_functional_writes; 987} 988''') 989 990 # Check if this controller has a peer, if yes then write the 991 # function for connecting to the peer. 992 if has_peer: 993 code(''' 994 995void 996$c_ident::getQueuesFromPeer(AbstractController *peer) 997{ 998''') 999 for var in self.objects: 1000 if "network" in var and "physical_network" in var and \ 1001 var["network"] == "From": 1002 code(''' 1003m_${{var.ident}}_ptr = peer->getPeerQueue(${{var["physical_network"]}}); 1004assert(m_${{var.ident}}_ptr != NULL); 1005m_${{var.ident}}_ptr->setReceiver(this); 1006 1007''') 1008 code('}') 1009 1010 code.write(path, "%s.cc" % c_ident) 1011 1012 def printCWakeup(self, path, includes): 1013 '''Output the wakeup loop for the events''' 1014 1015 code = self.symtab.codeFormatter() 1016 ident = self.ident 1017 1018 outputRequest_types = True 1019 if len(self.request_types) == 0: 1020 outputRequest_types = False 1021 1022 code(''' 1023// Auto generated C++ code started by $__file__:$__line__ 1024// ${ident}: ${{self.short}} 1025 1026#include <sys/types.h> 1027#include <unistd.h> 1028 1029#include <cassert> 1030 1031#include "base/misc.hh" 1032#include "debug/RubySlicc.hh" 1033#include "mem/protocol/${ident}_Controller.hh" 1034#include "mem/protocol/${ident}_Event.hh" 1035#include "mem/protocol/${ident}_State.hh" 1036''') 1037 1038 if outputRequest_types: 1039 code('''#include "mem/protocol/${ident}_RequestType.hh"''') 1040 1041 code(''' 1042#include "mem/protocol/Types.hh" 1043#include "mem/ruby/common/Global.hh" 1044#include "mem/ruby/system/System.hh" 1045''') 1046 1047 1048 for include_path in includes: 1049 code('#include "${{include_path}}"') 1050 1051 code(''' 1052 1053using namespace std; 1054 1055void 1056${ident}_Controller::wakeup() 1057{ 1058 int counter = 0; 1059 while (true) { 1060 // Some cases will put us into an infinite loop without this limit 1061 assert(counter <= m_transitions_per_cycle); 1062 if (counter == m_transitions_per_cycle) { 1063 // Count how often we are fully utilized 1064 m_fully_busy_cycles++; 1065 1066 // Wakeup in another cycle and try again 1067 scheduleEvent(Cycles(1)); 1068 break; 1069 } 1070''') 1071 1072 code.indent() 1073 code.indent() 1074 1075 # InPorts 1076 # 1077 for port in self.in_ports: 1078 code.indent() 1079 code('// ${ident}InPort $port') 1080 if port.pairs.has_key("rank"): 1081 code('m_cur_in_port = ${{port.pairs["rank"]}};') 1082 else: 1083 code('m_cur_in_port = 0;') 1084 code('${{port["c_code_in_port"]}}') 1085 code.dedent() 1086 1087 code('') 1088 1089 code.dedent() 1090 code.dedent() 1091 code(''' 1092 break; // If we got this far, we have nothing left todo 1093 } 1094} 1095''') 1096 1097 code.write(path, "%s_Wakeup.cc" % self.ident) 1098 1099 def printCSwitch(self, path): 1100 '''Output switch statement for transition table''' 1101 1102 code = self.symtab.codeFormatter() 1103 ident = self.ident 1104 1105 code(''' 1106// Auto generated C++ code started by $__file__:$__line__ 1107// ${ident}: ${{self.short}} 1108 1109#include <cassert> 1110 1111#include "base/misc.hh" 1112#include "base/trace.hh" 1113#include "debug/ProtocolTrace.hh" 1114#include "debug/RubyGenerated.hh" 1115#include "mem/protocol/${ident}_Controller.hh" 1116#include "mem/protocol/${ident}_Event.hh" 1117#include "mem/protocol/${ident}_State.hh" 1118#include "mem/protocol/Types.hh" 1119#include "mem/ruby/common/Global.hh" 1120#include "mem/ruby/system/System.hh" 1121 1122#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 1123 1124#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 1125#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 1126 1127TransitionResult 1128${ident}_Controller::doTransition(${ident}_Event event, 1129''') 1130 if self.EntryType != None: 1131 code(''' 1132 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 1133''') 1134 if self.TBEType != None: 1135 code(''' 1136 ${{self.TBEType.c_ident}}* m_tbe_ptr, 1137''') 1138 code(''' 1139 const Address addr) 1140{ 1141''') 1142 code.indent() 1143 1144 if self.TBEType != None and self.EntryType != None: 1145 code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 1146 elif self.TBEType != None: 1147 code('${ident}_State state = getState(m_tbe_ptr, addr);') 1148 elif self.EntryType != None: 1149 code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 1150 else: 1151 code('${ident}_State state = getState(addr);') 1152 1153 code(''' 1154${ident}_State next_state = state; 1155 1156DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 1157 *this, curCycle(), ${ident}_State_to_string(state), 1158 ${ident}_Event_to_string(event), addr); 1159 1160TransitionResult result = 1161''') 1162 if self.TBEType != None and self.EntryType != None: 1163 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 1164 elif self.TBEType != None: 1165 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 1166 elif self.EntryType != None: 1167 code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 1168 else: 1169 code('doTransitionWorker(event, state, next_state, addr);') 1170 1171 code(''' 1172 1173if (result == TransitionResult_Valid) { 1174 DPRINTF(RubyGenerated, "next_state: %s\\n", 1175 ${ident}_State_to_string(next_state)); 1176 countTransition(state, event); 1177 1178 DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 1179 curTick(), m_version, "${ident}", 1180 ${ident}_Event_to_string(event), 1181 ${ident}_State_to_string(state), 1182 ${ident}_State_to_string(next_state), 1183 addr, GET_TRANSITION_COMMENT()); 1184 1185 CLEAR_TRANSITION_COMMENT(); 1186''') 1187 if self.TBEType != None and self.EntryType != None: 1188 code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 1189 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1190 elif self.TBEType != None: 1191 code('setState(m_tbe_ptr, addr, next_state);') 1192 code('setAccessPermission(addr, next_state);') 1193 elif self.EntryType != None: 1194 code('setState(m_cache_entry_ptr, addr, next_state);') 1195 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1196 else: 1197 code('setState(addr, next_state);') 1198 code('setAccessPermission(addr, next_state);') 1199 1200 code(''' 1201} else if (result == TransitionResult_ResourceStall) { 1202 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1203 curTick(), m_version, "${ident}", 1204 ${ident}_Event_to_string(event), 1205 ${ident}_State_to_string(state), 1206 ${ident}_State_to_string(next_state), 1207 addr, "Resource Stall"); 1208} else if (result == TransitionResult_ProtocolStall) { 1209 DPRINTF(RubyGenerated, "stalling\\n"); 1210 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1211 curTick(), m_version, "${ident}", 1212 ${ident}_Event_to_string(event), 1213 ${ident}_State_to_string(state), 1214 ${ident}_State_to_string(next_state), 1215 addr, "Protocol Stall"); 1216} 1217 1218return result; 1219''') 1220 code.dedent() 1221 code(''' 1222} 1223 1224TransitionResult 1225${ident}_Controller::doTransitionWorker(${ident}_Event event, 1226 ${ident}_State state, 1227 ${ident}_State& next_state, 1228''') 1229 1230 if self.TBEType != None: 1231 code(''' 1232 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1233''') 1234 if self.EntryType != None: 1235 code(''' 1236 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1237''') 1238 code(''' 1239 const Address& addr) 1240{ 1241 switch(HASH_FUN(state, event)) { 1242''') 1243 1244 # This map will allow suppress generating duplicate code 1245 cases = orderdict() 1246 1247 for trans in self.transitions: 1248 case_string = "%s_State_%s, %s_Event_%s" % \ 1249 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1250 1251 case = self.symtab.codeFormatter() 1252 # Only set next_state if it changes 1253 if trans.state != trans.nextState: 1254 ns_ident = trans.nextState.ident 1255 case('next_state = ${ident}_State_${ns_ident};') 1256 1257 actions = trans.actions 1258 request_types = trans.request_types 1259 1260 # Check for resources 1261 case_sorter = [] 1262 res = trans.resources 1263 for key,val in res.iteritems(): 1264 val = ''' 1265if (!%s.areNSlotsAvailable(%s)) 1266 return TransitionResult_ResourceStall; 1267''' % (key.code, val) 1268 case_sorter.append(val) 1269 1270 # Check all of the request_types for resource constraints 1271 for request_type in request_types: 1272 val = ''' 1273if (!checkResourceAvailable(%s_RequestType_%s, addr)) { 1274 return TransitionResult_ResourceStall; 1275} 1276''' % (self.ident, request_type.ident) 1277 case_sorter.append(val) 1278 1279 # Emit the code sequences in a sorted order. This makes the 1280 # output deterministic (without this the output order can vary 1281 # since Map's keys() on a vector of pointers is not deterministic 1282 for c in sorted(case_sorter): 1283 case("$c") 1284 1285 # Record access types for this transition 1286 for request_type in request_types: 1287 case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 1288 1289 # Figure out if we stall 1290 stall = False 1291 for action in actions: 1292 if action.ident == "z_stall": 1293 stall = True 1294 break 1295 1296 if stall: 1297 case('return TransitionResult_ProtocolStall;') 1298 else: 1299 if self.TBEType != None and self.EntryType != None: 1300 for action in actions: 1301 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1302 elif self.TBEType != None: 1303 for action in actions: 1304 case('${{action.ident}}(m_tbe_ptr, addr);') 1305 elif self.EntryType != None: 1306 for action in actions: 1307 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1308 else: 1309 for action in actions: 1310 case('${{action.ident}}(addr);') 1311 case('return TransitionResult_Valid;') 1312 1313 case = str(case) 1314 1315 # Look to see if this transition code is unique. 1316 if case not in cases: 1317 cases[case] = [] 1318 1319 cases[case].append(case_string) 1320 1321 # Walk through all of the unique code blocks and spit out the 1322 # corresponding case statement elements 1323 for case,transitions in cases.iteritems(): 1324 # Iterative over all the multiple transitions that share 1325 # the same code 1326 for trans in transitions: 1327 code(' case HASH_FUN($trans):') 1328 code(' $case\n') 1329 1330 code(''' 1331 default: 1332 fatal("Invalid transition\\n" 1333 "%s time: %d addr: %s event: %s state: %s\\n", 1334 name(), curCycle(), addr, event, state); 1335 } 1336 1337 return TransitionResult_Valid; 1338} 1339''') 1340 code.write(path, "%s_Transitions.cc" % self.ident) 1341 1342 1343 # ************************** 1344 # ******* HTML Files ******* 1345 # ************************** 1346 def frameRef(self, click_href, click_target, over_href, over_num, text): 1347 code = self.symtab.codeFormatter(fix_newlines=False) 1348 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1349 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1350 parent.frames[$over_num].location='$over_href' 1351 }\"> 1352 ${{html.formatShorthand(text)}} 1353 </A>""") 1354 return str(code) 1355 1356 def writeHTMLFiles(self, path): 1357 # Create table with no row hilighted 1358 self.printHTMLTransitions(path, None) 1359 1360 # Generate transition tables 1361 for state in self.states.itervalues(): 1362 self.printHTMLTransitions(path, state) 1363 1364 # Generate action descriptions 1365 for action in self.actions.itervalues(): 1366 name = "%s_action_%s.html" % (self.ident, action.ident) 1367 code = html.createSymbol(action, "Action") 1368 code.write(path, name) 1369 1370 # Generate state descriptions 1371 for state in self.states.itervalues(): 1372 name = "%s_State_%s.html" % (self.ident, state.ident) 1373 code = html.createSymbol(state, "State") 1374 code.write(path, name) 1375 1376 # Generate event descriptions 1377 for event in self.events.itervalues(): 1378 name = "%s_Event_%s.html" % (self.ident, event.ident) 1379 code = html.createSymbol(event, "Event") 1380 code.write(path, name) 1381 1382 def printHTMLTransitions(self, path, active_state): 1383 code = self.symtab.codeFormatter() 1384 1385 code(''' 1386<HTML> 1387<BODY link="blue" vlink="blue"> 1388 1389<H1 align="center">${{html.formatShorthand(self.short)}}: 1390''') 1391 code.indent() 1392 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1393 mid = machine.ident 1394 if i != 0: 1395 extra = " - " 1396 else: 1397 extra = "" 1398 if machine == self: 1399 code('$extra$mid') 1400 else: 1401 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1402 code.dedent() 1403 1404 code(""" 1405</H1> 1406 1407<TABLE border=1> 1408<TR> 1409 <TH> </TH> 1410""") 1411 1412 for event in self.events.itervalues(): 1413 href = "%s_Event_%s.html" % (self.ident, event.ident) 1414 ref = self.frameRef(href, "Status", href, "1", event.short) 1415 code('<TH bgcolor=white>$ref</TH>') 1416 1417 code('</TR>') 1418 # -- Body of table 1419 for state in self.states.itervalues(): 1420 # -- Each row 1421 if state == active_state: 1422 color = "yellow" 1423 else: 1424 color = "white" 1425 1426 click = "%s_table_%s.html" % (self.ident, state.ident) 1427 over = "%s_State_%s.html" % (self.ident, state.ident) 1428 text = html.formatShorthand(state.short) 1429 ref = self.frameRef(click, "Table", over, "1", state.short) 1430 code(''' 1431<TR> 1432 <TH bgcolor=$color>$ref</TH> 1433''') 1434 1435 # -- One column for each event 1436 for event in self.events.itervalues(): 1437 trans = self.table.get((state,event), None) 1438 if trans is None: 1439 # This is the no transition case 1440 if state == active_state: 1441 color = "#C0C000" 1442 else: 1443 color = "lightgrey" 1444 1445 code('<TD bgcolor=$color> </TD>') 1446 continue 1447 1448 next = trans.nextState 1449 stall_action = False 1450 1451 # -- Get the actions 1452 for action in trans.actions: 1453 if action.ident == "z_stall" or \ 1454 action.ident == "zz_recycleMandatoryQueue": 1455 stall_action = True 1456 1457 # -- Print out "actions/next-state" 1458 if stall_action: 1459 if state == active_state: 1460 color = "#C0C000" 1461 else: 1462 color = "lightgrey" 1463 1464 elif active_state and next.ident == active_state.ident: 1465 color = "aqua" 1466 elif state == active_state: 1467 color = "yellow" 1468 else: 1469 color = "white" 1470 1471 code('<TD bgcolor=$color>') 1472 for action in trans.actions: 1473 href = "%s_action_%s.html" % (self.ident, action.ident) 1474 ref = self.frameRef(href, "Status", href, "1", 1475 action.short) 1476 code(' $ref') 1477 if next != state: 1478 if trans.actions: 1479 code('/') 1480 click = "%s_table_%s.html" % (self.ident, next.ident) 1481 over = "%s_State_%s.html" % (self.ident, next.ident) 1482 ref = self.frameRef(click, "Table", over, "1", next.short) 1483 code("$ref") 1484 code("</TD>") 1485 1486 # -- Each row 1487 if state == active_state: 1488 color = "yellow" 1489 else: 1490 color = "white" 1491 1492 click = "%s_table_%s.html" % (self.ident, state.ident) 1493 over = "%s_State_%s.html" % (self.ident, state.ident) 1494 ref = self.frameRef(click, "Table", over, "1", state.short) 1495 code(''' 1496 <TH bgcolor=$color>$ref</TH> 1497</TR> 1498''') 1499 code(''' 1500<!- Column footer-> 1501<TR> 1502 <TH> </TH> 1503''') 1504 1505 for event in self.events.itervalues(): 1506 href = "%s_Event_%s.html" % (self.ident, event.ident) 1507 ref = self.frameRef(href, "Status", href, "1", event.short) 1508 code('<TH bgcolor=white>$ref</TH>') 1509 code(''' 1510</TR> 1511</TABLE> 1512</BODY></HTML> 1513''') 1514 1515 1516 if active_state: 1517 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1518 else: 1519 name = "%s_table.html" % self.ident 1520 code.write(path, name) 1521 1522__all__ = [ "StateMachine" ]
|