forked from cdkersey/chdl
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbvec.h
125 lines (98 loc) · 3.31 KB
/
bvec.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
// A bvec is a fixed-length vector of bits.
#ifndef __BVEC_H
#define __BVEC_H
#include <cstdlib>
#include <initializer_list>
#include <vector>
#include "reg.h"
#include "lit.h"
#include "node.h"
namespace chdl {
// range is used to index a fixed-width subset of a vec
template <unsigned A, unsigned B> struct range{};
template <unsigned LEN, unsigned A> struct xrange{};
template <unsigned N, typename T> class vec;
template <unsigned N, typename T> class vec {
public:
virtual ~vec() {}
vec(): nodes(N) {}
vec(const T &r) {
nodes.reserve(N);
for (unsigned i = 0; i < N; ++i) nodes.push_back(r);
}
template <typename U> vec(const vec<N, U> &v) {
nodes.reserve(N);
for (unsigned i = 0; i < N; ++i) nodes.push_back(v[i]);
}
vec(const vec &v) {
nodes.reserve(N);
for (unsigned i = 0; i < N; ++i) nodes.push_back(v[i]);
}
vec(vec &v) {
nodes.reserve(N);
for (unsigned i = 0; i < N; ++i) nodes.push_back(v[i]);
}
vec(std::initializer_list<T> l) {
nodes.reserve(N);
unsigned i(0);
for (auto &x : l) { nodes.push_back(x); ++i; }
for (; i < N; ++i) nodes.push_back(T());
}
template <unsigned A> vec(const vec<A, T> &a, const vec<N-A, T> &b) {
nodes.reserve(N);
for (unsigned i = 0; i < N-A; ++i) nodes.push_back(b[i]);
for (unsigned i = 0; i < A; ++i) nodes.push_back(a[i]);
}
vec &operator=(const vec &r) {
for (unsigned i = 0; i < N; ++i) nodes[i] = r[i];
return *this;
}
const vec &operator=(const vec &r) const {
// This works because node has a const assignment operator.
for (unsigned i = 0; i < N; ++i) nodes[i] = r[i];
return *this;
}
template <typename U> vec &operator=(const vec<N, U> &r) {
for (unsigned i = 0; i < N; ++i) nodes[i] = r[i];
return *this;
}
// Indexing operators
typename std::vector<T>::reference operator[](size_t i) {
bc(i); return nodes[i];
}
typename std::vector<T>::const_reference operator[](size_t i) const {
bc(i); return nodes[i];
}
template <unsigned A> vec<0, T> operator[](const xrange<0, A> &r) const {
return vec<0, T>();
}
template <unsigned A> vec<1, T> operator[](const xrange<1, A> &r) const {
bc(A);
return vec<1, T>(nodes[A]);
}
template <unsigned A, unsigned LEN>
vec<LEN, T> operator[](const xrange<LEN, A> &r) const
{
return vec<LEN, T>((*this)[xrange<LEN-LEN/2,A+LEN/2>()],
(*this)[xrange<LEN/2,A>()]);
}
template <unsigned A, unsigned B>
vec<B-A+1, T> operator[](const range<A, B> &r) const
{
return (*this)[xrange<B-A+1, A>()];
}
protected:
std::vector<T> nodes;
private:
void bc(size_t i) const { if (i >= N) abort(); }
void bc(size_t i, size_t j) const { bc(i); bc(j); }
};
template <unsigned N> using bvec = vec<N, node>;
// TODO: Standardize this
template <typename T> struct sz { const static unsigned value = 0; };
template <> struct sz<node> { const static unsigned value = 1; };
template <unsigned N, typename T> struct sz<vec<N, T> > {
const static unsigned value = sz<T>::value * N;
};
};
#endif