ruby: get rid of RefCnt and Allocator stuff use base/refcnt.hh
[gem5.git] / src / mem / ruby / libruby.cc
1 /*
2 * Copyright (c) 2009 Mark D. Hill and David A. Wood
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 */
28
29 #include <sys/wait.h>
30 #include <algorithm>
31
32 #include "config/gems_root.hh"
33 #include "mem/ruby/common/Address.hh"
34 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
35 #include "mem/ruby/libruby_internal.hh"
36 #include "mem/ruby/recorder/Tracer.hh"
37 #include "mem/ruby/system/MemoryVector.hh"
38 #include "mem/ruby/system/RubyPort.hh"
39 #include "mem/ruby/system/System.hh"
40
41 using namespace std;
42
43 string
44 RubyRequestType_to_string(const RubyRequestType& obj)
45 {
46 switch(obj) {
47 case RubyRequestType_IFETCH:
48 return "IFETCH";
49 case RubyRequestType_LD:
50 return "LD";
51 case RubyRequestType_ST:
52 return "ST";
53 case RubyRequestType_Locked_Read:
54 return "Locked_Read";
55 case RubyRequestType_Locked_Write:
56 return "Locked_Write";
57 case RubyRequestType_RMW_Read:
58 return "RMW_Read";
59 case RubyRequestType_RMW_Write:
60 return "RMW_Write";
61 case RubyRequestType_NULL:
62 default:
63 assert(0);
64 return "";
65 }
66 }
67
68 RubyRequestType
69 string_to_RubyRequestType(string str)
70 {
71 if (str == "IFETCH")
72 return RubyRequestType_IFETCH;
73 else if (str == "LD")
74 return RubyRequestType_LD;
75 else if (str == "ST")
76 return RubyRequestType_ST;
77 else if (str == "Locked_Read")
78 return RubyRequestType_Locked_Read;
79 else if (str == "Locked_Write")
80 return RubyRequestType_Locked_Write;
81 else if (str == "RMW_Read")
82 return RubyRequestType_RMW_Read;
83 else if (str == "RMW_Write")
84 return RubyRequestType_RMW_Write;
85 else
86 assert(0);
87 return RubyRequestType_NULL;
88 }
89
90 ostream&
91 operator<<(ostream& out, const RubyRequestType& obj)
92 {
93 out << RubyRequestType_to_string(obj);
94 out << flush;
95 return out;
96 }
97
98 ostream&
99 operator<<(ostream& out, const RubyRequest& obj)
100 {
101 out << hex << "0x" << obj.paddr << " data: 0x" << flush;
102 for (int i = 0; i < obj.len; i++) {
103 out << (int)obj.data[i];
104 }
105 out << dec << " type: " << RubyRequestType_to_string(obj.type) << endl;
106 return out;
107 }
108
109 vector<string>
110 tokenizeString(string str, string delims)
111 {
112 vector<string> tokens;
113 char* pch;
114 char* tmp;
115 const char* c_delims = delims.c_str();
116 tmp = new char[str.length()+1];
117 strcpy(tmp, str.c_str());
118 pch = strtok(tmp, c_delims);
119 while (pch != NULL) {
120 string tmp_str(pch);
121 if (tmp_str == "null") tmp_str = "";
122 tokens.push_back(tmp_str);
123
124 pch = strtok(NULL, c_delims);
125 }
126 delete [] tmp;
127 return tokens;
128 }
129
130 /*
131 * The current state of M5/Ruby integration breaks the libruby
132 * interface. This code is ifdef'd out for now so that we can move
133 * forward with the integration process for non-libruby uses. We'll
134 * have to go back and resolve the libruby compatibility issue at a
135 * later date.
136 */
137 #if 0
138 void
139 libruby_init(const char* cfg_filename)
140 {
141 ifstream cfg_output(cfg_filename);
142
143 vector<RubyObjConf> * sys_conf = new vector<RubyObjConf>;
144
145 string line;
146 getline(cfg_output, line) ;
147 while ( !cfg_output.eof() ) {
148 vector<string> tokens = tokenizeString(line, " ");
149 assert(tokens.size() >= 2);
150 vector<string> argv;
151 for (size_t i=2; i<tokens.size(); i++) {
152 replace(tokens[i].begin(), tokens[i].end(), '%', ' ');
153 replace(tokens[i].begin(), tokens[i].end(), '#', '\n');
154 argv.push_back(tokens[i]);
155 }
156 sys_conf->push_back(RubyObjConf(tokens[0], tokens[1], argv));
157 tokens.clear();
158 argv.clear();
159 getline(cfg_output, line);
160 }
161
162 RubySystem::create(*sys_conf);
163 delete sys_conf;
164 }
165 #endif
166
167 RubyPortHandle
168 libruby_get_port(const char* port_name,
169 void (*hit_callback)(int64_t access_id))
170 {
171 //
172 // Fix me: Hit callback is now a non-static member function pointer of
173 // RubyPort and cannot be set to an arbitrary global function
174 //
175 return NULL;//static_cast<RubyPortHandle>(RubySystem::getPort(port_name, hit_callback));
176 }
177
178 RubyPortHandle libruby_get_port_by_name(const char* port_name)
179 {
180 //
181 // Fix me: Ports should now be initialized using the python configuration
182 // system
183 //
184 return NULL;//static_cast<RubyPortHandle>(RubySystem::getPortOnly(port_name));
185 }
186
187 void
188 libruby_write_ram(uint64_t paddr, uint8_t* data, int len)
189 {
190 RubySystem::getMemoryVector()->write(Address(paddr), data, len);
191 }
192
193 void
194 libruby_read_ram(uint64_t paddr, uint8_t* data, int len)
195 {
196 RubySystem::getMemoryVector()->read(Address(paddr), data, len);
197 }
198
199 int64_t
200 libruby_issue_request(RubyPortHandle p, struct RubyRequest request)
201 {
202 //
203 // Fix me: Ports should now be accessed using the python configuration
204 // system
205 //
206 return 0;//return static_cast<RubyPort*>(p)->makeRequest(request);
207 }
208
209 int
210 libruby_tick(int n)
211 {
212 RubyEventQueue *eventq = RubySystem::getEventQueue();
213 eventq->triggerEvents(eventq->getTime() + n);
214 return 0;
215 }
216
217 void
218 libruby_destroy()
219 {
220 }
221
222 const char*
223 libruby_last_error()
224 {
225 return "";
226 }
227
228 void
229 libruby_print_config(ostream & out)
230 {
231 RubySystem::printConfig(out);
232 }
233
234 void
235 libruby_print_stats(ostream & out)
236 {
237 RubySystem::printStats(out);
238 }
239 void
240 libruby_playback_trace(char * trace_filename)
241 {
242 RubySystem::getTracer()->playbackTrace(trace_filename);
243 }
244
245 void
246 libruby_start_tracing(char * record_filename)
247 {
248 // start the trace
249 RubySystem::getTracer()->startTrace(record_filename);
250 }
251
252 void
253 libruby_stop_tracing()
254 {
255 // start the trace
256 RubySystem::getTracer()->stopTrace();
257 }
258
259 uint64_t
260 libruby_get_time()
261 {
262 return RubySystem::getCycleCount(0);
263 }