Permalink
Browse files

Implement replies to sswitch read / write commands. This is enough to…

… get

a multicore g4 binary to run.
  • Loading branch information...
1 parent f406fa1 commit 248d0c15b9b5d9d19dd96bbb2e1fb9a93a409c63 @rlsosborne rlsosborne committed Jul 24, 2011
Showing with 290 additions and 42 deletions.
  1. +1 −1 Chanend.cpp
  2. +1 −1 Node.h
  3. +1 −1 README.rst
  4. +1 −1 Resource.h
  5. +115 −13 SSwitch.cpp
  6. +27 −2 SSwitch.h
  7. +7 −7 SyscallHandler.cpp
  8. +4 −5 SystemState.cpp
  9. +2 −0 Token.h
  10. +113 −1 Trace.cpp
  11. +10 −1 Trace.h
  12. +8 −8 main.cpp
  13. +0 −1 test/multicore_g4.xc
View
@@ -18,7 +18,7 @@ bool Chanend::canAcceptTokens(unsigned tokens)
void Chanend::receiveDataToken(ticks_t time, uint8_t value)
{
- buf.push_back(Token(value, time));
+ buf.push_back(Token(value));
scheduleUpdate(time);
}
View
2 Node.h
@@ -28,7 +28,7 @@ class Node {
Type type;
SSwitch sswitch;
public:
- Node(Type t) : jtagIndex(0), nodeID(0), parent(0), type(t) {}
+ Node(Type t) : jtagIndex(0), nodeID(0), parent(0), type(t), sswitch(this) {}
~Node();
void addCore(std::auto_ptr<Core> cores);
void setJtagIndex(unsigned value) { jtagIndex = value; }
View
@@ -19,7 +19,7 @@ Known Issues
* No simulation of the boot ROM.
* No simulation of debug.
* No support for configurable delays on ports / clocks.
-* No support for reading and writing of pswitch / sswitch registers.
+* Minimal support for reading and writing of pswitch / sswitch registers.
* No support for partial inputs / output (INPW, OUTPW, SETPSC).
* There are a few other miscellaneous instructions that are unimplemented.
* The loopback option (--loopback) can only be used to connect ports on the
View
@@ -105,7 +105,7 @@ class ResourceID {
operator uint32_t() const { return id; }
- static ResourceID chanendID(unsigned num, uint32_t node)
+ static ResourceID chanendID(unsigned num, uint16_t node)
{
return RES_TYPE_CHANEND | (num << RES_NUM_SHIFT) |
(node << RES_CHANEND_NODE_SHIFT);
View
@@ -4,28 +4,66 @@
// LICENSE.txt and at <http://github.xcore.com/>
#include "SSwitch.h"
+#include "Resource.h"
+#include "Node.h"
+#include "SystemState.h"
+#include "Trace.h"
#include <cassert>
+SSwitchCtrlRegs::SSwitchCtrlRegs() : scratchReg(0)
+{
+
+}
+
+bool SSwitchCtrlRegs::read(uint16_t num, uint32_t &result)
+{
+ if (num != 3) {
+ return false;
+ }
+ result = scratchReg;
+ return true;
+}
-SSwitch::SSwitch() :
+bool SSwitchCtrlRegs::write(uint16_t num, uint32_t value)
+{
+ if (num != 3) {
+ return false;
+ }
+ scratchReg = value;
+ return true;
+}
+
+SSwitch::SSwitch(Node *p) :
+ parent(p),
recievedTokens(0),
- junkIncomingTokens(0)
+ junkIncomingTokens(0),
+ sendingResponse(false),
+ sentTokens(0),
+ responseLength(0)
{
setJunkIncoming(false);
}
-static uint16_t read16_be(Token *p)
+static uint16_t read16_be(const Token *p)
{
return (p[0].getValue() << 8) | p[1].getValue();
}
-static uint32_t read32_be(Token *p)
+static uint32_t read32_be(const Token *p)
{
return (p[0].getValue() << 24) | (p[1].getValue() << 16) |
(p[2].getValue() << 8) | p[3].getValue();
}
-static bool containsControlToken(Token *p, unsigned size)
+static void write32_be(Token *p, uint32_t value)
+{
+ p[0] = Token(value >> 24);
+ p[1] = Token((value >> 16) & 0xff);
+ p[2] = Token((value >> 8) & 0xff);
+ p[3] = Token(value & 0xff);
+}
+
+static bool containsControlToken(const Token *p, unsigned size)
{
for (unsigned i = 0; i < size; ++i) {
if (p[i].isControl())
@@ -34,7 +72,7 @@ static bool containsControlToken(Token *p, unsigned size)
return false;
}
-bool SSwitch::parseRequest(Request &request)
+bool SSwitch::parseRequest(ticks_t time, Request &request) const
{
if (recievedTokens == 0)
return false;
@@ -68,6 +106,66 @@ bool SSwitch::parseRequest(Request &request)
return true;
}
+void SSwitch::handleRequest(ticks_t time, const Request &request)
+{
+ bool ack;
+ uint32_t value = 0;
+ ResourceID destID = ResourceID::chanendID(request.returnNum,
+ request.returnNode);
+ if (request.write) {
+ ack = regs.write(request.regNum, request.data);
+ if (Tracer::get().getTracingEnabled()) {
+ Tracer::get().SSwitchWrite(*parent, destID, request.regNum, request.data);
+ if (ack)
+ Tracer::get().SSwitchAck(*parent, destID);
+ else
+ Tracer::get().SSwitchNack(*parent, destID);
+ }
+ } else {
+ ack = regs.read(request.regNum, value);
+ if (Tracer::get().getTracingEnabled()) {
+ Tracer::get().SSwitchRead(*parent, destID, request.regNum);
+ if (ack)
+ Tracer::get().SSwitchAck(*parent, value, destID);
+ else
+ Tracer::get().SSwitchNack(*parent, destID);
+ }
+ }
+ ChanEndpoint *dest = parent->getParent()->getChanendDest(destID);
+ if (!dest)
+ return;
+ bool junkPacket = false;
+ if (!dest->claim(this, junkPacket)) {
+ assert(0 && "TODO");
+ }
+ if (junkPacket)
+ return;
+ sendingResponse = true;
+ sentTokens = 0;
+ responseLength = 0;
+ if (ack) {
+ buf[responseLength++] = Token(CT_ACK, true);
+ if (!request.write) {
+ write32_be(&buf[responseLength], value);
+ responseLength += 4;
+ }
+ } else {
+ buf[responseLength++] = Token(CT_NACK, true);
+ }
+ buf[responseLength++] = Token(CT_END, true);
+ if (!dest->canAcceptTokens(responseLength)) {
+ assert(0 && "TODO");
+ }
+ for (unsigned i = 0; i < responseLength; i++) {
+ if (buf[i].isControl()) {
+ dest->receiveCtrlToken(time, buf[i].getValue());
+ } else {
+ dest->receiveDataToken(time, buf[i].getValue());
+ }
+ }
+ sendingResponse = false;
+}
+
void SSwitch::notifyDestClaimed(ticks_t time)
{
// TODO
@@ -82,12 +180,12 @@ void SSwitch::notifyDestCanAcceptTokens(ticks_t time, unsigned tokens)
bool SSwitch::canAcceptToken()
{
- return true;
+ return !sendingResponse;
}
bool SSwitch::canAcceptTokens(unsigned tokens)
{
- return true;
+ return !sendingResponse;
}
void SSwitch::receiveDataToken(ticks_t time, uint8_t value)
@@ -118,17 +216,21 @@ void SSwitch::receiveDataTokens(ticks_t time, uint8_t *values, unsigned num)
void SSwitch::receiveCtrlToken(ticks_t time, uint8_t value)
{
- if (value == CT_END) {
+ switch (value) {
+ case CT_END:
Request request;
- if (!junkIncomingTokens && parseRequest(request)) {
- // TODO
- assert(0);
+ if (!junkIncomingTokens && parseRequest(time, request)) {
+ handleRequest(time, request);
}
recievedTokens = 0;
junkIncomingTokens = false;
+ release(time);
+ return;
+ case CT_PAUSE:
+ release(time);
return;
}
- if (junkIncomingTokens || value == CT_PAUSE) {
+ if (junkIncomingTokens) {
return;
}
if (recievedTokens == writeRequestLength) {
View
@@ -3,9 +3,23 @@
// University of Illinois/NCSA Open Source License posted in
// LICENSE.txt and at <http://github.xcore.com/>
+#ifndef _SSwitch_h_
+#define _SSwitch_h_
+
#include "Token.h"
#include "ChanEndpoint.h"
+class Node;
+
+class SSwitchCtrlRegs {
+private:
+ uint32_t scratchReg;
+public:
+ SSwitchCtrlRegs();
+ bool read(uint16_t num, uint32_t &result);
+ bool write(uint16_t num, uint32_t value);
+};
+
class SSwitch : public ChanEndpoint {
private:
struct Request {
@@ -15,6 +29,8 @@ class SSwitch : public ChanEndpoint {
uint32_t regNum;
uint32_t data;
};
+ Node *parent;
+ SSwitchCtrlRegs regs;
/// Length of a write request (excluding CT_END).
static const unsigned writeRequestLength = 1 + 3 + 2 + 4;
/// Length of a read request (excluding CT_END).
@@ -23,9 +39,15 @@ class SSwitch : public ChanEndpoint {
unsigned recievedTokens;
Token buf[writeRequestLength];
bool junkIncomingTokens;
- bool parseRequest(Request &request);
+ /// Are we in the middle of sending a response?
+ bool sendingResponse;
+ unsigned sentTokens;
+ /// Length of response (including CT_END).
+ unsigned responseLength;
+ bool parseRequest(ticks_t time, Request &request) const;
+ void handleRequest(ticks_t time, const Request &request);
public:
- SSwitch();
+ SSwitch(Node *parent);
virtual void notifyDestClaimed(ticks_t time);
virtual void notifyDestCanAcceptTokens(ticks_t time, unsigned tokens);
@@ -39,3 +61,6 @@ class SSwitch : public ChanEndpoint {
virtual void receiveCtrlToken(ticks_t time, uint8_t value);
};
+
+#endif _SSwitch_h_
+
View
@@ -229,21 +229,21 @@ void SyscallHandlerImpl::doException(const ThreadState &thread)
#define TRACE_BEGIN() \
do { \
-if (Tracer::getInstance().getTracingEnabled()) { \
-Tracer::getInstance().syscall(thread); \
+if (Tracer::get().getTracingEnabled()) { \
+Tracer::get().syscall(thread); \
} \
} while(0)
#define TRACE_END() \
do { \
-if (Tracer::getInstance().getTracingEnabled()) { \
-Tracer::getInstance().traceEnd(); \
+if (Tracer::get().getTracingEnabled()) { \
+Tracer::get().traceEnd(); \
} \
} while(0)
#define TRACE(...) \
do { \
-if (Tracer::getInstance().getTracingEnabled()) { \
-Tracer::getInstance().syscall(thread, __VA_ARGS__); \
-Tracer::getInstance().traceEnd(); \
+if (Tracer::get().getTracingEnabled()) { \
+Tracer::get().syscall(thread, __VA_ARGS__); \
+Tracer::get().traceEnd(); \
} \
} while(0)
#define TRACE_REG_WRITE(register, value) \
View
@@ -30,7 +30,7 @@ ThreadState *SystemState::deschedule(ThreadState &current)
currentThread = 0;
handleNonThreads();
if (scheduler.empty()) {
- Tracer::getInstance().noRunnableThreads(*this);
+ Tracer::get().noRunnableThreads(*this);
current.pc = current.getParent().getNoThreadsAddr();
current.waiting() = false;
currentThread = &current;
@@ -58,14 +58,13 @@ completeEvent(ThreadState &t, EventableResource &res, bool interrupt)
t.eeble() = false;
// EventableResource::completeEvent sets the ED and PC.
res.completeEvent();
- if (Tracer::getInstance().getTracingEnabled()) {
+ if (Tracer::get().getTracingEnabled()) {
if (interrupt) {
- Tracer::getInstance().interrupt(t, res, t.getParent().targetPc(t.pc),
+ Tracer::get().interrupt(t, res, t.getParent().targetPc(t.pc),
t.regs[SSR], t.regs[SPC], t.regs[SED],
t.regs[ED]);
} else {
- Tracer::getInstance().event(t, res, t.getParent().targetPc(t.pc),
- t.regs[ED]);
+ Tracer::get().event(t, res, t.getParent().targetPc(t.pc), t.regs[ED]);
}
}
}
View
@@ -11,6 +11,8 @@
enum ControlTokenValue {
CT_END = 1,
CT_PAUSE = 2,
+ CT_ACK = 3,
+ CT_NACK = 4,
CT_WRITEC = 0xc0,
CT_READC = 0xc1
};
Oops, something went wrong.

0 comments on commit 248d0c1

Please sign in to comment.