Skip to content

Commit c965a6f

Browse files
Merge pull request #18 from Capital-Asterisk/0.1.3-maybe
A bunch of improvements and stuff for 0.2.0
2 parents 243f3c8 + fd0d6b9 commit c965a6f

File tree

17 files changed

+761
-410
lines changed

17 files changed

+761
-410
lines changed

examples/circuits/circuit_builder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ ElementId gate_combinatinal(CombinationalGates::GateDesc desc, std::initializer_
4040
void populate_pub_sub(Elements const& elements, Nodes &rNodes)
4141
{
4242
std::vector<int> nodeSubCount(rNodes.m_nodeIds.capacity(), 0); // can we reach 1 million subscribers?
43-
for (ElementId elem : elements.m_ids.bitview().zeros())
43+
for (ElementId elem : elements.m_ids)
4444
{
4545
auto nodes = rNodes.m_elemConnect[elem];
4646
// skip first, port 0 is the publisher

examples/circuits/circuits.hpp

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#pragma once
66

77
#include <longeron/containers/intarray_multimap.hpp>
8+
#include <longeron/id_management/id_set_stl.hpp>
9+
#include <longeron/id_management/keyed_vec_stl.hpp>
810
#include <longeron/id_management/registry_stl.hpp>
911

1012
#include <algorithm>
@@ -13,31 +15,37 @@
1315
namespace circuits
1416
{
1517

16-
using ElementId = uint32_t;
17-
using ElemLocalId = uint32_t;
18-
using ElemTypeId = uint8_t;
19-
using NodeId = uint32_t;
18+
19+
// Enum classes used as integer "strong typedef" and can't be implicitly casted to each other,
20+
// preventing logic errors and cognative load from accidentally mixing them up.
21+
enum class ElemLocalId : std::uint32_t { };
22+
enum class ElemTypeId : std::uint8_t { };
23+
24+
// lgrn::IntArrayMultiMap does not (yet?) support strongly typedefed ID types
25+
using ElementId = std::uint32_t;
26+
using NodeId = std::uint32_t;
27+
2028

2129
/**
2230
* @brief Keeps track of which circuit elements of a certain type exists
2331
*/
2432
struct PerElemType
2533
{
26-
lgrn::IdRegistryStl<ElemLocalId> m_localIds;
27-
std::vector<ElementId> m_localToElem;
34+
lgrn::IdRegistryStl<ElemLocalId> m_localIds;
35+
lgrn::KeyedVec<ElemLocalId, ElementId> m_localToElem;
2836
};
2937

3038
/**
3139
* @brief Keeps track of which circuit elements exist and what type they are
3240
*/
3341
struct Elements
3442
{
35-
lgrn::IdRegistryStl<ElementId> m_ids;
43+
lgrn::IdRegistryStl<ElementId> m_ids;
3644

37-
std::vector<ElemTypeId> m_elemTypes;
38-
std::vector<ElemLocalId> m_elemToLocal;
45+
lgrn::KeyedVec<ElementId, ElemTypeId> m_elemTypes;
46+
lgrn::KeyedVec<ElementId, ElemLocalId> m_elemToLocal;
3947

40-
std::vector<PerElemType> m_perType;
48+
lgrn::KeyedVec<ElemTypeId, PerElemType> m_perType;
4149
};
4250

4351
/**
@@ -49,6 +57,7 @@ struct ElementPair
4957
ElemTypeId m_type;
5058
};
5159

60+
5261
/**
5362
* @brief Connects cirucit elements together as Nodes
5463
*/
@@ -64,7 +73,7 @@ struct Nodes
6473
// Node-to-Element connections
6574
// Each node can have multiple subscribers, but only one publisher
6675
Subscribers_t m_nodeSubscribers;
67-
std::vector<ElementId> m_nodePublisher;
76+
lgrn::KeyedVec<NodeId, ElementId> m_nodePublisher;
6877

6978
// Corresponding Element-to-Node connections
7079
// [ElementId][PortId] -> NodeId
@@ -80,7 +89,7 @@ struct Nodes
8089
template <typename VALUE_T>
8190
struct NodeValues
8291
{
83-
std::vector<VALUE_T> m_nodeValues;
92+
lgrn::KeyedVec<NodeId, VALUE_T> m_nodeValues;
8493
};
8594

8695
//-----------------------------------------------------------------------------
@@ -102,33 +111,31 @@ struct CombinationalGates
102111
bool m_invert;
103112
};
104113

105-
std::vector<GateDesc> m_localGates;
114+
lgrn::KeyedVec<ElemLocalId, GateDesc> m_localGates;
106115
};
107116

108117
//-----------------------------------------------------------------------------
109118

110119
// Updating
111120

112-
using BitVector_t = lgrn::BitView< std::vector<uint64_t> >;
113-
114121
constexpr std::size_t const gc_bitVecIntSize = 64;
115122

116123
struct UpdateElem
117124
{
118-
BitVector_t m_localDirty;
125+
lgrn::IdSetStl<ElemLocalId> m_localDirty;
119126
};
120127

121-
using UpdateElemTypes_t = std::vector<UpdateElem>;
128+
using UpdateElemTypes_t = lgrn::KeyedVec<ElemTypeId, UpdateElem>;
122129

123130
template <typename VALUE_T>
124131
struct UpdateNodes
125132
{
126-
BitVector_t m_nodeDirty;
127-
std::vector<VALUE_T> m_nodeNewValues;
133+
lgrn::IdSetStl<NodeId> m_nodeDirty;
134+
lgrn::KeyedVec<NodeId, VALUE_T> m_nodeNewValues;
128135

129136
void assign(NodeId node, VALUE_T&& value)
130137
{
131-
m_nodeDirty.set(node);
138+
m_nodeDirty.insert(node);
132139
m_nodeNewValues[node] = std::forward<VALUE_T>(value);
133140
}
134141
};
@@ -147,26 +154,26 @@ struct UpdateNodes
147154
*/
148155
template <typename RANGE_T>
149156
bool update_combinational(
150-
RANGE_T&& toUpdate,
151-
ElementId const* pLocalToElem,
152-
Nodes::Connections_t const& elemConnect,
153-
ELogic const* pNodeValues,
154-
CombinationalGates const& gates,
155-
UpdateNodes<ELogic>& rUpdNodes) noexcept
157+
RANGE_T&& toUpdate,
158+
lgrn::KeyedVec<ElemLocalId, ElementId> const &localToElem,
159+
Nodes::Connections_t const &elemConnect,
160+
lgrn::KeyedVec<NodeId, ELogic> &nodeValues,
161+
CombinationalGates const &gates,
162+
UpdateNodes<ELogic> &rUpdNodes) noexcept
156163
{
157164
using Op = CombinationalGates::Op;
158165

159-
auto const is_logic_high = [pNodeValues] (NodeId in) noexcept -> bool
166+
auto const is_logic_high = [&nodeValues] (NodeId in) noexcept -> bool
160167
{
161-
return pNodeValues[in] == ELogic::High;
168+
return nodeValues[in] == ELogic::High;
162169
};
163170

164171
bool nodeUpdated = false;
165172

166173
for (ElemLocalId local : toUpdate)
167174
{
168-
ElementId const elem = pLocalToElem[local];
169-
CombinationalGates::GateDesc const& desc = gates.m_localGates[local];
175+
ElementId const elem = localToElem[local];
176+
CombinationalGates::GateDesc const &desc = gates.m_localGates[local];
170177

171178
auto connectedNodes = elemConnect[elem];
172179
auto inFirst = connectedNodes.begin() + 1;
@@ -197,10 +204,10 @@ bool update_combinational(
197204
NodeId out = *connectedNodes.begin();
198205

199206
// Request to write changes to node if value is changed
200-
if (pNodeValues[out] != outLogic)
207+
if (nodeValues[out] != outLogic)
201208
{
202209
nodeUpdated = true;
203-
rUpdNodes.m_nodeDirty.set(out);
210+
rUpdNodes.m_nodeDirty.insert(out);
204211
rUpdNodes.m_nodeNewValues[out] = outLogic;
205212
}
206213
}
@@ -222,25 +229,24 @@ bool update_combinational(
222229
*/
223230
template <typename VALUE_T, typename RANGE_T>
224231
bool update_nodes(
225-
RANGE_T&& toUpdate,
226-
Nodes::Subscribers_t const& nodeSubs,
227-
Elements const& elements,
228-
VALUE_T const* pNewValues,
229-
VALUE_T* pValues,
230-
UpdateElemTypes_t& rUpdElem)
232+
RANGE_T &&toUpdate,
233+
Nodes::Subscribers_t const &nodeSubs,
234+
lgrn::KeyedVec<NodeId, VALUE_T> const &newValues,
235+
lgrn::KeyedVec<NodeId, VALUE_T> &values,
236+
UpdateElemTypes_t &rUpdElem)
231237
{
232238
bool elemNotified = false;
233239

234-
for (uint32_t node : toUpdate)
240+
for (NodeId node : toUpdate)
235241
{
236242
// Apply node value changes
237-
pValues[node] = pNewValues[node];
243+
values[node] = newValues[node];
238244

239245
// Notify subscribed elements
240246
for (ElementPair subElem : nodeSubs[node])
241247
{
242248
elemNotified = true;
243-
rUpdElem[subElem.m_type].m_localDirty.set(subElem.m_id);
249+
rUpdElem[subElem.m_type].m_localDirty.insert(subElem.m_id);
244250
}
245251
}
246252

examples/circuits/main.cpp

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include <iostream>
1414
#include <vector>
1515

16-
#include <optional>
17-
1816
using namespace circuits;
1917

2018
using lgrn::id_null;
@@ -72,15 +70,15 @@ struct UserCircuit
7270
{
7371
UpdateElemTypes_t out;
7472
out.resize(m_maxTypes);
75-
out[gc_elemGate].m_localDirty.ints().resize(m_elements.m_perType[gc_elemGate].m_localIds.vec().capacity());
73+
out[gc_elemGate].m_localDirty.resize(m_elements.m_perType[gc_elemGate].m_localIds.capacity());
7674

7775
// Initially set all to dirty get to valid state
7876
// middle parts of a circuit may be unresponsive otherwise
79-
for (uint32_t elem : m_elements.m_ids.bitview().zeros())
77+
for (ElementId elem : m_elements.m_ids)
8078
{
81-
ElemTypeId const type = m_elements.m_elemTypes[elem];
79+
ElemTypeId const type = m_elements.m_elemTypes[elem];
8280
ElemLocalId const local = m_elements.m_elemToLocal[elem];
83-
out[type].m_localDirty.set(local);
81+
out[type].m_localDirty.insert(local);
8482
}
8583

8684
return out;
@@ -89,7 +87,7 @@ struct UserCircuit
8987
UpdateNodes<ELogic> setup_logic_updater()
9088
{
9189
UpdateNodes<ELogic> out;
92-
out.m_nodeDirty.ints().resize(m_maxNodes / gc_bitVecIntSize + 1);
90+
out.m_nodeDirty.resize(m_maxNodes);
9391
out.m_nodeNewValues.resize(m_maxNodes);
9492

9593
return out;
@@ -133,22 +131,21 @@ static int step_until_stable(
133131
while (elemNotified && steps < maxSteps)
134132
{
135133
update_nodes(
136-
rUpdLogic.m_nodeDirty.ones(),
134+
rUpdLogic.m_nodeDirty,
137135
rCircuit.m_logicNodes.m_nodeSubscribers,
138-
rCircuit.m_elements,
139-
rUpdLogic.m_nodeNewValues.data(),
140-
rCircuit.m_logicValues.m_nodeValues.data(),
136+
rUpdLogic.m_nodeNewValues,
137+
rCircuit.m_logicValues.m_nodeValues,
141138
rUpdElems);
142-
rUpdLogic.m_nodeDirty.reset();
139+
rUpdLogic.m_nodeDirty.clear();
143140

144141
elemNotified = update_combinational(
145-
rUpdElems[gc_elemGate].m_localDirty.ones(),
146-
rCircuit.m_elements.m_perType[gc_elemGate].m_localToElem.data(),
142+
rUpdElems[gc_elemGate].m_localDirty,
143+
rCircuit.m_elements.m_perType[gc_elemGate].m_localToElem,
147144
rCircuit.m_logicNodes.m_elemConnect,
148-
rCircuit.m_logicValues.m_nodeValues.data(),
145+
rCircuit.m_logicValues.m_nodeValues,
149146
rCircuit.m_gates,
150147
rUpdLogic);
151-
rUpdElems[gc_elemGate].m_localDirty.reset();
148+
rUpdElems[gc_elemGate].m_localDirty.clear();
152149

153150
steps ++;
154151
}
@@ -244,7 +241,7 @@ static void test_manual_build()
244241

245242
// Connect 'ports' of XOR gate. Adds a Element->Node mapping
246243
// For basic gates, first (0) is the output, the rest are inputs
247-
circuit.m_logicNodes.m_elemConnect.emplace(gc_elemGate, {out, A, B});
244+
circuit.m_logicNodes.m_elemConnect.emplace(xorElem, {out, A, B});
248245

249246
// Connect publishers and subscribers. Adds Node->Element mapping
250247
circuit.m_logicNodes.m_nodePublisher[out] = xorElem;
@@ -253,7 +250,7 @@ static void test_manual_build()
253250

254251
// Now everything is set, circuit can run!
255252

256-
UpdateElemTypes_t updElems = circuit.setup_element_updater();
253+
UpdateElemTypes_t updElems = circuit.setup_element_updater();
257254
UpdateNodes<ELogic> updLogic = circuit.setup_logic_updater();
258255

259256
auto const& outVal = circuit.m_logicValues.m_nodeValues[out];
@@ -308,7 +305,7 @@ static void test_xor_nand()
308305

309306
circuit.build_end();
310307

311-
UpdateElemTypes_t updElems = circuit.setup_element_updater();
308+
UpdateElemTypes_t updElems = circuit.setup_element_updater();
312309
UpdateNodes<ELogic> updLogic = circuit.setup_logic_updater();
313310

314311
auto const& outVal = circuit.m_logicValues.m_nodeValues[out];
@@ -361,9 +358,9 @@ static void test_sr_latch()
361358
// initialize to get to valid state
362359
for (uint32_t elem : circuit.m_elements.m_ids.bitview().zeros())
363360
{
364-
ElemTypeId const type = circuit.m_elements.m_elemTypes[elem];
361+
ElemTypeId const type = circuit.m_elements.m_elemTypes[elem];
365362
ElemLocalId const local = circuit.m_elements.m_elemToLocal[elem];
366-
updElems[type].m_localDirty.set(local);
363+
updElems[type].m_localDirty.insert(local);
367364
}
368365

369366
std::cout << "NAND SR latch:\n";
@@ -417,9 +414,9 @@ static void test_edge_detect()
417414
// initialize to get to valid state
418415
for (uint32_t elem : circuit.m_elements.m_ids.bitview().zeros())
419416
{
420-
ElemTypeId const type = circuit.m_elements.m_elemTypes[elem];
417+
ElemTypeId const type = circuit.m_elements.m_elemTypes[elem];
421418
ElemLocalId const local = circuit.m_elements.m_elemToLocal[elem];
422-
updElems[type].m_localDirty.set(local);
419+
updElems[type].m_localDirty.insert(local);
423420
}
424421

425422
std::cout << "Edge Detector:\n";

0 commit comments

Comments
 (0)