forked from xcore/tool_axe
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Chanend.h
131 lines (107 loc) · 4.49 KB
/
Chanend.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) 2011, Richard Osborne, All rights reserved
// This software is freely distributable under a derivative of the
// University of Illinois/NCSA Open Source License posted in
// LICENSE.txt and at <http://github.xcore.com/>
#ifndef _Chanend_h_
#define _Chanend_h_
#include "Resource.h"
#include "ChanEndpoint.h"
#include "ring_buffer.h"
#include "Token.h"
class Chanend : public EventableResource, public ChanEndpoint {
private:
// The destination resource ID.
uint32_t destID;
/// The destination channel end. Only valid when in the the middle of a
/// packet.
ChanEndpoint *dest;
/// Input buffer.
typedef ring_buffer<Token, CHANEND_BUFFER_SIZE> TokenBuffer;
TokenBuffer buf;
/// Thread paused on an output instruction, 0 if none.
Thread *pausedOut;
/// Thread paused on an input instruction, 0 if none.
Thread *pausedIn;
/// Is the pausedIn thread waiting for a word? Only valid if pausedIn is set.
bool waitForWord;
/// Are we in the middle of sending a packet?
bool inPacket;
/// Should be current packet be junked?
bool junkPacket;
/// Update the channel end after the data is placed in the buffer.
void update(ticks_t time);
/// Try and open a route for a packet. If a route cannot be opened the chanend
/// is registered with the destination and notifyDestClaimed() will be called
/// when the route becomes available.
bool openRoute();
/// Called when trying to open a route to this channel end. If the route
/// cannot be opened immediately then the source chanend is added to a queue.
/// The source will be notified when the route becomes available with
/// notifyDestClaimed().
/// \return Whether a route was succesfully opened.
bool claim(ChanEndpoint *Source, bool &junkPacket);
bool canAcceptToken();
bool canAcceptTokens(unsigned tokens);
/// Recieve data token. The caller must check sufficient room is available
/// using canAcceptToken().
void receiveDataToken(ticks_t time, uint8_t value);
/// Recieve data tokens. The caller must check sufficient room is available
/// using canAcceptTokens().
void receiveDataTokens(ticks_t time, uint8_t *values, unsigned num);
/// Recieve control token. The caller must check sufficient room is available
/// using canAcceptTokens().
void receiveCtrlToken(ticks_t time, uint8_t value);
/// Give notification that a route to the destination has been opened.
void notifyDestClaimed(ticks_t time);
/// Give notification that the destination can accept in the buffer has
/// become available.
void notifyDestCanAcceptTokens(ticks_t time, unsigned tokens);
/// Input a token. You must check beforehand if there is data available.
uint8_t poptoken(ticks_t time);
void setPausedIn(Thread &t, bool wordInput);
public:
Chanend() : EventableResource(RES_TYPE_CHANEND) {}
bool alloc(Thread &t)
{
assert(!isInUse() && "Trying to allocate in use chanend");
dest = 0;
pausedOut = 0;
pausedIn = 0;
inPacket = false;
junkPacket = false;
eventableSetInUseOn(t);
setJunkIncoming(false);
return true;
}
bool free()
{
if (!buf.empty() || getSource() || inPacket) {
return false;
}
eventableSetInUseOff();
setJunkIncoming(true);
return true;
}
bool setData(Thread &thread, uint32_t value, ticks_t time);
ResOpResult outt(Thread &thread, uint8_t value, ticks_t time);
ResOpResult outct(Thread &thread, uint8_t value, ticks_t time);
ResOpResult out(Thread &thread, uint32_t value, ticks_t time);
ResOpResult intoken(Thread &thread, ticks_t time, uint32_t &val);
ResOpResult inct(Thread &thread, ticks_t time, uint32_t &val);
ResOpResult chkct(Thread &thread, ticks_t time, uint32_t value);
/// Check if there is a token available for input. If a token is available
/// the current thread's time is adjusted to be after the time at which the
/// token was received and IsCt is set according whether it is a control token.
bool testct(Thread &thread, ticks_t time, bool &isCt);
/// Check if there is a word available for input. If a word is available
/// the current thread's time is adjusted to be after the time at which the
/// last token was received. Position is set to be the index of the first
/// control token, starting at one, or 0 if there is no control token in the
/// word.
bool testwct(Thread &thread, ticks_t time, unsigned &position);
ResOpResult in(Thread &thread, ticks_t time, uint32_t &val);
void run(ticks_t time);
protected:
bool seeEventEnable(ticks_t time);
};
#endif // _Chanend_h_