1 /*
2  * CvcTypes.hh
3  *
4  * Copyright 2014-2018 D. Mitch Bailey  cvc at shuharisystem dot com
5  *
6  * This file is part of cvc.
7  *
8  * cvc is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * cvc is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with cvc.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  * You can download cvc from https://github.com/d-m-bailey/cvc.git
22  */
23 
24 #ifndef CVCTYPES_HH_
25 #define CVCTYPES_HH_
26 
27 #include <cstdint>
28 #include <string>
29 #include <sstream>
30 #include <cstring>
31 #include <stdexcept>
32 #include <cstdlib>
33 #include <unordered_map>
34 
35 #ifndef INT64_MAX
36 #define INT64_MAX INT32_MAX
37 #endif
38 
39 typedef uint32_t netId_t;
40 typedef uint32_t deviceId_t;
41 typedef uint32_t instanceId_t;
42 
43 typedef int16_t	voltage_t;
44 typedef uint32_t resistance_t;
45 typedef int32_t eventKey_t;
46 
47 // Max resistance is 1G. Anything over that truncates to 1G with a warning.
48 #define INFINITE_RESISTANCE (UINT32_MAX)
49 #define MAX_RESISTANCE ((UINT32_MAX >> 2) - 1)
50 
51 #define VOLTAGE_SCALE 1000
52 #define MAX_VOLTAGE (INT16_MAX - 1)
53 #define MIN_VOLTAGE (INT16_MIN + 1)
54 
55 #define MIN_EVENT_TIME (INT32_MIN)
56 #define MAX_EVENT_TIME (INT32_MAX)
57 
58 #define MAX_NET (UINT32_MAX - 1)
59 #define MAX_DEVICE (UINT32_MAX - 1)
60 #define MAX_SUBCIRCUIT (UINT32_MAX - 1)
61 
62 #define UNKNOWN_NET UINT32_MAX
63 #define UNKNOWN_SUBCIRCUIT UINT32_MAX
64 #define UNKNOWN_DEVICE UINT32_MAX
65 #define UNKNOWN_INSTANCE UINT32_MAX
66 
67 #define UNKNOWN_VOLTAGE (INT16_MAX)
68 
69 #define DEFAULT_MOS_RESISTANCE "L/W*7000"
70 #define DEFAULT_RESISTANCE "R"
71 #define DEFAULT_UNKNOWN_RESISTANCE 1100100
72 
73 #define MAX_PARALLEL_CIRCUIT_PORT_LIMIT 10
74 
75 #define HIERARCHY_DELIMITER	"/"
76 #define ALIAS_DELIMITER "~>"
77 
78 #define IsMos_(theDeviceType) ((theDeviceType) == NMOS || (theDeviceType) == PMOS || (theDeviceType) == LDDN || (theDeviceType) == LDDP)
79 #define IsNmos_(theDeviceType) ((theDeviceType) == NMOS || (theDeviceType) == LDDN)
80 #define IsPmos_(theDeviceType) ((theDeviceType) == PMOS || (theDeviceType) == LDDP)
81 
82 #define IsLesserVoltage_(theFirstVoltage, theSecondVoltage) (theFirstVoltage != UNKNOWN_VOLTAGE && theSecondVoltage != UNKNOWN_VOLTAGE && theFirstVoltage < theSecondVoltage)
83 #define IsLesserOrEqualVoltage_(theFirstVoltage, theSecondVoltage) (theFirstVoltage != UNKNOWN_VOLTAGE && theSecondVoltage != UNKNOWN_VOLTAGE && theFirstVoltage <= theSecondVoltage)
84 #define IsEqualVoltage_(theFirstVoltage, theSecondVoltage) (theFirstVoltage != UNKNOWN_VOLTAGE && theSecondVoltage != UNKNOWN_VOLTAGE && theFirstVoltage == theSecondVoltage)
85 #define IsGreaterVoltage_(theFirstVoltage, theSecondVoltage) (theFirstVoltage != UNKNOWN_VOLTAGE && theSecondVoltage != UNKNOWN_VOLTAGE && theFirstVoltage > theSecondVoltage)
86 #define IsGreaterOrEqualVoltage_(theFirstVoltage, theSecondVoltage) (theFirstVoltage != UNKNOWN_VOLTAGE && theSecondVoltage != UNKNOWN_VOLTAGE && theFirstVoltage >= theSecondVoltage)
87 
from_string(std::string const & s)88 template <typename T> T from_string(std::string const & s) {
89 	std::stringstream ss(s);
90 	T result;
91 	static const std::unordered_map<std::string, float> SISuffix = {
92 		{"a", 1e-18},
93 		{"f", 1e-15},
94 		{"p", 1e-12},
95 		{"n", 1e-9},
96 		{"u", 1e-6},
97 		{"m", 1e-3},
98 		{"K", 1e3},
99 		{"M", 1e6},
100 		{"G", 1e9},
101 		{"T", 1e12},
102 		{"P", 1e15},
103 		{"E", 1e18}
104 	};
105 	std::string mySuffix = "";
106 	ss >> result;	// TODO handle errors
107 	ss >> mySuffix;
108 	if ( mySuffix != "" ) {
109 		result = result * SISuffix.at(mySuffix);
110 	}
111 	return result;
112 }
113 
to_string(T theValue)114 template <typename T> std::string to_string(T theValue) {
115 	std::ostringstream convert;
116 	convert << theValue;
117 	return convert.str();
118 }
119 
120 enum relation_t { equals, lessThan, greaterThan, notLessThan, notGreaterThan };
121 
122 // also used as bit offset in source connection status. do not use any offsets after fuse
123 enum modelType_t { NMOS = 0, PMOS, RESISTOR, CAPACITOR, DIODE, BIPOLAR, FUSE_ON, FUSE_OFF,
124 	SWITCH_ON, SWITCH_OFF, MOSFET, LDDN, LDDP, BOX, UNKNOWN };
125 
126 enum eventQueue_t { SIM_QUEUE, MAX_QUEUE, MIN_QUEUE };
127 
128 enum queueStatus_t { ENQUEUE, DEQUEUE };
129 
130 enum deviceStatus_t { MIN_INACTIVE = 0, MIN_PENDING, MAX_INACTIVE, MAX_PENDING, SIM_INACTIVE, SIM_PENDING };
131 
132 enum netStatus_t { ANALOG = 0, MIN_POWER, SIM_POWER, MAX_POWER, NEEDS_MIN_CHECK, NEEDS_MAX_CHECK, NEEDS_MIN_CONNECTION, NEEDS_MAX_CONNECTION };
133 // NEEDS_MIN/MAX_CHECK for min/max prop through pmos/nmos
134 // NEEDS_MIN/MAX_CONNECTION for pmos/nmos connected as diode
135 
136 enum shortDirection_t { SOURCE_TO_MASTER_DRAIN, DRAIN_TO_MASTER_SOURCE };
137 
138 enum terminal_t { GATE = 1, SOURCE = 2, GS, DRAIN = 4, GD, SD, GSD, BULK = 8, GB, SB, GSB, DB, GDB, SDB, GSDB };
139 
140 enum propagation_t { POWER_NETS_ONLY = 1, ALL_NETS_NO_FUSE, ALL_NETS_AND_FUSE };
141 
142 enum cvcError_t { LEAK = 0, HIZ_INPUT, FORWARD_DIODE, NMOS_SOURCE_BULK, NMOS_GATE_SOURCE, NMOS_POSSIBLE_LEAK,
143 	PMOS_SOURCE_BULK, PMOS_GATE_SOURCE, PMOS_POSSIBLE_LEAK, OVERVOLTAGE_VBG, OVERVOLTAGE_VBS, OVERVOLTAGE_VDS,
144 	OVERVOLTAGE_VGS, MODEL_CHECK, EXPECTED_VOLTAGE, LDD_SOURCE, MIN_VOLTAGE_CONFLICT, MAX_VOLTAGE_CONFLICT, FUSE_ERROR, ERROR_TYPE_COUNT };
145 // Flag Constants
146 
147 #define PRINT_CIRCUIT_ON	true
148 #define PRINT_CIRCUIT_OFF	false
149 #define PRINT_HIERARCHY_ON	true
150 #define PRINT_HIERARCHY_OFF	false
151 
152 #define PRINT_DEVICE_LIST_ON	true
153 #define PRINT_DEVICE_LIST_OFF	false
154 
155 #define ZERO_DELAY	0
156 
157 #define RESISTOR_ONLY 0x04
158 
159 // teebuf from http://wordaligned.org/articles/cpp-streambufs
160 
161 #include <streambuf>
162 
163 class teebuf: public std::streambuf
164 {
165 public:
166 	// Construct a streambuf which tees output to both input
167 	// streambufs.
teebuf(std::streambuf * sb1,std::streambuf * sb2)168 	teebuf(std::streambuf * sb1, std::streambuf * sb2)
169 		: sb1(sb1)
170 		, sb2(sb2)
171 	{
172 	}
173 private:
174 	// This tee buffer has no buffer. So every character "overflows"
175 	// and can be put directly into the teed buffers.
overflow(int c)176 	virtual int overflow(int c)
177 	{
178 		if (c == traits_type::eof())
179 		{
180 			return !traits_type::eof();
181 		}
182 		else
183 		{
184 			int const r1 = sb1->sputc(c);
185 			int const r2 = sb2->sputc(c);
186 			return r1 == traits_type::eof() || r2 == traits_type::eof() ? traits_type::eof() : c;
187 		}
188 	}
189 
190 	// Sync both teed buffers.
sync()191 	virtual int sync()
192 	{
193 		int const r1 = sb1->pubsync();
194 		int const r2 = sb2->pubsync();
195 		return r1 == 0 && r2 == 0 ? 0 : -1;
196 	}
197 private:
198 	std::streambuf * sb1;
199 	std::streambuf * sb2;
200 };
201 
202 class teestream : public std::ostream
203 {
204 public:
205 	// Construct an ostream which tees output to the supplied
206 	// ostreams.
teestream(std::ostream & o1,std::ostream & o2)207 	teestream(std::ostream & o1, std::ostream & o2) : std::ostream(&tbuf), tbuf(o1.rdbuf(), o2.rdbuf()) {};
208 private:
209 	teebuf tbuf;
210 };
211 
212 // end teebuf
213 
214 #endif /* CVCTYPES_HH_ */
215