summaryrefslogtreecommitdiff
path: root/src/mem/slicc
diff options
context:
space:
mode:
authorDerek Hower <drh5@cs.wisc.edu>2010-01-19 17:11:36 -0600
committerDerek Hower <drh5@cs.wisc.edu>2010-01-19 17:11:36 -0600
commit07ea0891f1699f6194a05516948ce3824fb8fb38 (patch)
treeb5c22e3fe49a7e0d277fdb9ac5ee87c2aa0321e5 /src/mem/slicc
parent279f179babc9e5663156777c533c06edc91bce9a (diff)
downloadgem5-07ea0891f1699f6194a05516948ce3824fb8fb38.tar.xz
ruby: new atomics implementation
This patch changes the way that Ruby handles atomic RMW instructions. This implementation, unlike the prior one, is protocol independent. It works by locking an address from the sequencer immediately after the read portion of an RMW completes. When that address is locked, the coherence controller will only satisfy requests coming from one port (e.g., the mandatory queue) and will ignore all others. After the write portion completed, the line is unlocked. This should also work with multi-line atomics, as long as the blocks are always acquired in the same order.
Diffstat (limited to 'src/mem/slicc')
-rw-r--r--src/mem/slicc/ast/PeekStatementAST.py15
-rw-r--r--src/mem/slicc/parser.py4
-rw-r--r--src/mem/slicc/symbols/StateMachine.py156
3 files changed, 30 insertions, 145 deletions
diff --git a/src/mem/slicc/ast/PeekStatementAST.py b/src/mem/slicc/ast/PeekStatementAST.py
index 5186bf0d5..b63ce6516 100644
--- a/src/mem/slicc/ast/PeekStatementAST.py
+++ b/src/mem/slicc/ast/PeekStatementAST.py
@@ -29,8 +29,8 @@ from slicc.ast.StatementAST import StatementAST
from slicc.symbols import Var
class PeekStatementAST(StatementAST):
- def __init__(self, slicc, queue_name, type_ast, statements, method):
- super(PeekStatementAST, self).__init__(slicc)
+ def __init__(self, slicc, queue_name, type_ast, pairs, statements, method):
+ super(PeekStatementAST, self).__init__(slicc, pairs)
self.queue_name = queue_name
self.type_ast = type_ast
@@ -63,6 +63,17 @@ class PeekStatementAST(StatementAST):
in_msg_ptr = dynamic_cast<const $mtid *>(($qcode).${{self.method}}());
assert(in_msg_ptr != NULL);
''')
+ if self.pairs.has_key("block_on"):
+ address_field = self.pairs['block_on']
+ code('''
+ if ( (m_is_blocking == true) &&
+ (m_block_map.count(in_msg_ptr->m_$address_field) == 1) ) {
+ if (m_block_map[in_msg_ptr->m_$address_field] != &$qcode) {
+ $qcode.delayHead();
+ continue;
+ }
+ }
+ ''')
# The other statements
self.statements.generate(code, return_type)
diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py
index 6c3f45629..226106678 100644
--- a/src/mem/slicc/parser.py
+++ b/src/mem/slicc/parser.py
@@ -514,8 +514,8 @@ class SLICC(Grammar):
p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[6], p[8])
def p_statement__peek(self, p):
- "statement : PEEK '(' var ',' type ')' statements"
- p[0] = ast.PeekStatementAST(self, p[3], p[5], p[7], "peek")
+ "statement : PEEK '(' var ',' type pairs ')' statements"
+ p[0] = ast.PeekStatementAST(self, p[3], p[5], p[6], p[8], "peek")
def p_statement__copy_head(self, p):
"statement : COPY_HEAD '(' var ',' var pairs ')' SEMI"
diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py
index af9850896..73c3fe720 100644
--- a/src/mem/slicc/symbols/StateMachine.py
+++ b/src/mem/slicc/symbols/StateMachine.py
@@ -185,11 +185,10 @@ public:
void print(ostream& out) const;
void printConfig(ostream& out) const;
void wakeup();
- void set_atomic(Address addr);
- void clear_atomic(Address addr);
- void reset_atomics();
void printStats(ostream& out) const { s_profiler.dumpStats(out); }
void clearStats() { s_profiler.clearStats(); }
+ void blockOnQueue(Address addr, MessageBuffer* port);
+ void unblock(Address addr);
private:
''')
@@ -198,16 +197,6 @@ private:
for param in self.config_parameters:
code('int m_${{param.ident}};')
- if self.ident == "L1Cache":
- code('''
-int servicing_atomic;
-Address locked_read_request1;
-Address locked_read_request2;
-Address locked_read_request3;
-Address locked_read_request4;
-int read_counter;
-''')
-
code('''
int m_number_of_TBEs;
@@ -221,6 +210,8 @@ map< string, string > m_cfg;
NodeID m_version;
Network* m_net_ptr;
MachineID m_machineID;
+bool m_is_blocking;
+map< Address, MessageBuffer* > m_block_map;
${ident}_Profiler s_profiler;
static int m_num_controllers;
// Internal functions
@@ -297,15 +288,6 @@ $c_ident::$c_ident(const string &name)
{
''')
code.indent()
- if self.ident == "L1Cache":
- code('''
-servicing_atomic = 0;
-locked_read_request1 = Address(-1);
-locked_read_request2 = Address(-1);
-locked_read_request3 = Address(-1);
-locked_read_request4 = Address(-1);
-read_counter = 0;
-''')
code('m_num_controllers++;')
for var in self.objects:
@@ -515,6 +497,17 @@ const MachineType $c_ident::getMachineType() const{
return MachineType_${ident};
}
+void $c_ident::blockOnQueue(Address addr, MessageBuffer* port) {
+ m_is_blocking = true;
+ m_block_map[addr] = port;
+}
+void $c_ident::unblock(Address addr) {
+ m_block_map.erase(addr);
+ if (m_block_map.size() == 0) {
+ m_is_blocking = false;
+ }
+}
+
void $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; }
void $c_ident::printConfig(ostream& out) const {
@@ -580,54 +573,12 @@ void ${ident}_Controller::wakeup()
# InPorts
#
- # Find the position of the mandatory queue in the vector so
- # that we can print it out first
-
- mandatory_q = None
- if self.ident == "L1Cache":
- for i,port in enumerate(self.in_ports):
- assert "c_code_in_port" in port
- if str(port).find("mandatoryQueue_in") >= 0:
- assert mandatory_q is None
- mandatory_q = port
-
- assert mandatory_q is not None
-
- # print out the mandatory queue here
- port = mandatory_q
- code('// ${ident}InPort $port')
- output = port["c_code_in_port"]
-
- code('$output')
-
for port in self.in_ports:
- # don't print out mandatory queue twice
- if port == mandatory_q:
- continue
-
- if ident == "L1Cache":
- if (str(port).find("forwardRequestNetwork_in") >= 0 or str(port).find("requestNetwork_in") >= 0 or str(port).find("requestIntraChipL1Network_in") >= 0):
- code('''
-bool postpone = false;
-if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) {
- const RequestMsg* in_msg_ptr;
- in_msg_ptr = dynamic_cast<const RequestMsg*>(((*m_L1Cache_forwardToCache_ptr)).peek());
- if ((((servicing_atomic > 0) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || locked_read_request1 == ((*in_msg_ptr)).m_Address)))) {
- postpone = true;
- }
-}
-if (!postpone) {
-''')
code.indent()
code('// ${ident}InPort $port')
code('${{port["c_code_in_port"]}}')
code.dedent()
- if ident == "L1Cache":
- if (str(port).find("forwardRequestNetwork_in") >= 0 or str(port).find("requestNetwork_in") >= 0 or str(port).find("requestIntraChipL1Network_in") >= 0):
- code.dedent()
- code('}')
- code.indent()
code('')
code.dedent()
@@ -638,83 +589,6 @@ if (!postpone) {
}
''')
- if self.ident == "L1Cache":
- code('''
-void ${ident}_Controller::set_atomic(Address addr)
-{
- servicing_atomic++;
- switch (servicing_atomic) {
- case(1):
- assert(locked_read_request1 == Address(-1));
- locked_read_request1 = addr;
- break;
- case(2):
- assert(locked_read_request2 == Address(-1));
- locked_read_request2 = addr;
- break;
- case(3):
- assert(locked_read_request3 == Address(-1));
- locked_read_request3 = addr;
- break;
- case(4):
- assert(locked_read_request4 == Address(-1));
- locked_read_request4 = addr;
- break;
- default:
- assert(0);
-
- }
-}
-
-void ${ident}_Controller::clear_atomic(Address addr)
-{
-
- assert(servicing_atomic > 0);
- if (addr == locked_read_request1)
- locked_read_request1 = Address(-1);
- else if (addr == locked_read_request2)
- locked_read_request2 = Address(-1);
- else if (addr == locked_read_request3)
- locked_read_request3 = Address(-1);
- else if (addr == locked_read_request4)
- locked_read_request4 = Address(-1);
- else
- assert(0);
- servicing_atomic--;
-
-}
-
-void ${ident}_Controller::reset_atomics()
-{
-
- servicing_atomic = 0;
- locked_read_request1 = Address(-1);
- locked_read_request2 = Address(-1);
- locked_read_request3 = Address(-1);
- locked_read_request4 = Address(-1);
-
-}
-
-''')
- else:
- code('''
-void ${ident}_Controller::reset_atomics()
-{
- assert(0);
-}
-
-void ${ident}_Controller::set_atomic(Address addr)
-{
- assert(0);
-}
-
-void ${ident}_Controller::clear_atomic(Address addr)
-{
- assert(0);
-}
-''')
-
-
code.write(path, "%s_Wakeup.cc" % self.ident)
def printCSwitch(self, path):