|
| 1 | +<?xml version="1.0"?> |
| 2 | +<Graphs xmlns="https://poets-project.org/schemas/virtual-graph-schema-v2"> |
| 3 | + <GraphType id="ro"> |
| 4 | + <Documentation>Ring Oscillator</Documentation> |
| 5 | + <MetaData>"native_dimension":2</MetaData> |
| 6 | + <Properties/> |
| 7 | + |
| 8 | + <SharedCode> |
| 9 | + <![CDATA[ |
| 10 | + #define SOFTWARE_BUFF_SIZE 1024 |
| 11 | + // (Queue) send functions |
| 12 | +
|
| 13 | +// Note: buffer pointers point to the next available slot |
| 14 | +
|
| 15 | +struct toggle_msg { |
| 16 | + uint32_t src; |
| 17 | + uint32_t dst; |
| 18 | +}; |
| 19 | +
|
| 20 | +void send_toggle(ro_node_state_t *deviceState, toggle_msg *msg) { |
| 21 | +
|
| 22 | + uint32_t ind = (deviceState->toggle_buffer_ptr)++; |
| 23 | +
|
| 24 | + if (ind >= SOFTWARE_BUFF_SIZE ) { |
| 25 | + handler_log(1, "Error, outgoing toggle message buffer is full"); |
| 26 | + handler_exit(1); |
| 27 | + } |
| 28 | +
|
| 29 | + deviceState->toggle_buffer_dst[ind] = msg->dst; |
| 30 | +
|
| 31 | +} |
| 32 | + |
| 33 | + ]]> |
| 34 | + |
| 35 | + </SharedCode> |
| 36 | + |
| 37 | + <MessageTypes> |
| 38 | + |
| 39 | + <MessageType id="__init__"> |
| 40 | + <Documentation>Initialize state</Documentation> |
| 41 | + </MessageType> |
| 42 | + |
| 43 | + <MessageType id="toggle"> |
| 44 | + <Documentation>Toggle next node</Documentation> |
| 45 | + <Message> |
| 46 | + <Scalar type="uint32_t" name="src"> |
| 47 | + <Documentation>Source node id</Documentation> |
| 48 | + </Scalar> |
| 49 | + <Scalar type="uint32_t" name="dst"> |
| 50 | + <Documentation>Destination node id</Documentation> |
| 51 | + </Scalar> |
| 52 | + </Message> |
| 53 | + </MessageType> |
| 54 | + </MessageTypes> |
| 55 | + |
| 56 | + <DeviceTypes> |
| 57 | + <!-- Generated Block --> |
| 58 | + <DeviceType id="node"> |
| 59 | + <Properties> |
| 60 | + <Scalar name="id" type="uint32_t"></Scalar> |
| 61 | + <Scalar name="outdegree" type="uint32_t"></Scalar> |
| 62 | + </Properties> |
| 63 | + |
| 64 | + <State> |
| 65 | + |
| 66 | + <!-- Device state fields: --> |
| 67 | + <Scalar name="state" type="uint32_t"></Scalar> |
| 68 | + <Scalar name="counter" type="uint32_t"></Scalar> |
| 69 | + <!-- Software buffer for (outgoing) toggle messages: --> |
| 70 | + |
| 71 | + <Array name="toggle_buffer_dst" type="uint32_t" length="1024"></Array> |
| 72 | + <Scalar name="toggle_buffer_ptr" type="uint32_t"></Scalar> |
| 73 | + </State> |
| 74 | + |
| 75 | + <ReadyToSend> |
| 76 | + <![CDATA[ |
| 77 | +
|
| 78 | + |
| 79 | +bool pending_toggle_messages = deviceState->toggle_buffer_ptr > 0; |
| 80 | +
|
| 81 | +*readyToSend = |
| 82 | + (pending_toggle_messages ? RTS_FLAG_toggle_out : 0); |
| 83 | +
|
| 84 | + ]]> |
| 85 | + </ReadyToSend> |
| 86 | + |
| 87 | + <InputPin messageTypeId="__init__" name="__init__"> |
| 88 | + <OnReceive> |
| 89 | + <![CDATA[ |
| 90 | +
|
| 91 | + bool is_root = deviceProperties->id == 0; |
| 92 | +
|
| 93 | +deviceState->state = is_root ? 1 : 0; |
| 94 | +deviceState->counter = 0; |
| 95 | +
|
| 96 | +if (is_root) { |
| 97 | +
|
| 98 | + handler_log(1, "counter = %d", ++(deviceState->counter)); |
| 99 | +
|
| 100 | + // send initial message |
| 101 | + toggle_msg outgoing; |
| 102 | + outgoing.dst = 0xFFFFFFFF; // broadcast |
| 103 | + send_toggle(deviceState, &outgoing); |
| 104 | +} |
| 105 | +
|
| 106 | + ]]> |
| 107 | + </OnReceive> |
| 108 | + </InputPin> |
| 109 | + |
| 110 | + <InputPin messageTypeId="toggle" name="toggle_in"> |
| 111 | + <OnReceive> |
| 112 | + <![CDATA[ |
| 113 | +
|
| 114 | + bool finished = deviceState->counter >= 10; |
| 115 | +
|
| 116 | +if (finished) { |
| 117 | +
|
| 118 | + handler_exit(0); |
| 119 | +
|
| 120 | +} else { |
| 121 | +
|
| 122 | + handler_log(1, "counter = %d", ++(deviceState->counter)); |
| 123 | +
|
| 124 | + // toggle state: |
| 125 | + deviceState->state = 1 - deviceState->state; |
| 126 | +
|
| 127 | + // send message to next node: |
| 128 | + toggle_msg outgoing; |
| 129 | + outgoing.dst = 0xFFFFFFFF; // broadcast |
| 130 | + send_toggle(deviceState, &outgoing); |
| 131 | +
|
| 132 | +} |
| 133 | +
|
| 134 | + ]]> |
| 135 | + </OnReceive> |
| 136 | + </InputPin> |
| 137 | + |
| 138 | + <OutputPin messageTypeId="toggle" name="toggle_out"> |
| 139 | + <OnSend> |
| 140 | + <![CDATA[ |
| 141 | +
|
| 142 | + if (deviceState->toggle_buffer_ptr == 0) { |
| 143 | + // If this is executed, it is most likely due to an error in ready_to_send |
| 144 | + handler_log(1, "Error, attempted to send while buffer is empty"); |
| 145 | + handler_exit(1); |
| 146 | +} |
| 147 | +
|
| 148 | +uint32_t ind = --(deviceState->toggle_buffer_ptr); |
| 149 | +
|
| 150 | +message->src = deviceProperties->id; |
| 151 | +message->dst = deviceState->toggle_buffer_dst[ind]; |
| 152 | +
|
| 153 | + ]]> |
| 154 | + </OnSend> |
| 155 | + </OutputPin> |
| 156 | + |
| 157 | + </DeviceType> |
| 158 | + |
| 159 | + </DeviceTypes> |
| 160 | + </GraphType> |
| 161 | + <GraphInstance id="graph1" graphTypeId="ro"> |
| 162 | + <DeviceInstances> |
| 163 | + <DevI id="n0" type="node"> |
| 164 | + <P> |
| 165 | + "id": 0, |
| 166 | + "outdegree": 1 |
| 167 | + |
| 168 | + </P> |
| 169 | + </DevI> |
| 170 | + <DevI id="n1" type="node"> |
| 171 | + <P> |
| 172 | + "id": 1, |
| 173 | + "outdegree": 1 |
| 174 | + |
| 175 | + </P> |
| 176 | + </DevI> |
| 177 | + <DevI id="n2" type="node"> |
| 178 | + <P> |
| 179 | + "id": 2, |
| 180 | + "outdegree": 1 |
| 181 | + |
| 182 | + </P> |
| 183 | + </DevI> |
| 184 | + <DevI id="n3" type="node"> |
| 185 | + <P> |
| 186 | + "id": 3, |
| 187 | + "outdegree": 1 |
| 188 | + |
| 189 | + </P> |
| 190 | + </DevI> |
| 191 | + </DeviceInstances> |
| 192 | + <EdgeInstances> |
| 193 | + <EdgeI path="n1:toggle_in-n0:toggle_out"/> |
| 194 | + <EdgeI path="n2:toggle_in-n1:toggle_out"/> |
| 195 | + <EdgeI path="n3:toggle_in-n2:toggle_out"/> |
| 196 | + <EdgeI path="n0:toggle_in-n3:toggle_out"/> |
| 197 | + </EdgeInstances> |
| 198 | +</GraphInstance> |
| 199 | +</Graphs> |
0 commit comments