-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDsimModel.cpp
179 lines (146 loc) · 5.51 KB
/
DsimModel.cpp
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#define _CRT_SECURE_NO_WARNINGS // fopen_s is not available in older Windows versions
#include "DsimModel.h"
#include <stdio.h>
#include <string.h>
INT DsimModel::isdigital(CHAR* pinname) {
return TRUE; // Indicates all the pins are digital
}
VOID DsimModel::setup(IINSTANCE* instance, IDSIMCKT* dsimckt) {
_inst = instance;
_ckt = dsimckt;
/* connect control pins */
_ce_pin = _inst->getdsimpin((char*)"$CE$", true); _ce_pin->setstate(FLT);
_we_pin = _inst->getdsimpin((char*)"$WE$", false); if (_we_pin) _we_pin->setstate(FLT);
_oe_pin = _inst->getdsimpin((char*)"$OE$", false);
if (!_oe_pin) _oe_pin = _inst->getdsimpin((char*)"$OE$/VPP", true); // OE is often multiplexed with VPP (eg. 27C32)
_oe_pin->setstate(FLT);
char pin_name[4];
/* connect data pins */
pin_name[0] = 'D'; pin_name[2] = '\0'; // we only need to change pin_name[1] to '0' through '7'
for (size_t i = 0; i < 8; i++) {
pin_name[1] = (char)i + '0';
_data_pins[i] = _inst->getdsimpin(pin_name, true);
_data_pins[i]->setstate(FLT);
}
/* connect address pins */
pin_name[0] = 'A';
for (size_t i = 0; ; i++) {
snprintf(&pin_name[1], 3, "%d", (int)i);
IDSIMPIN* pin = _inst->getdsimpin(pin_name, false); // will return NULL if the pin isn't found
if (!pin) break; // no more pins to discover
pin->setstate(FLT);
_addr_pins.push_back(pin);
}
size_t size = 1ULL << _addr_pins.size();
if (size == 1) {
_inst->fatal((char*)"No address pins found!"); // 1 << 0
return;
}
_memory = new uint8_t[size]; // allocate memory buffer
memset(_memory, _inst->getinitval((char*)"INITVAL", 0xFF), size);
_inst->message((char*)"Simulating a %lu byte parallel %s.", size, (_we_pin) ? "RAM" : "ROM");
/* read initial memory dump if applicable */
const char* mem_file_name = _inst->getstrval((char*)"FILE");
if (mem_file_name && mem_file_name[0]) {
/* file specified */
FILE* mem_file = fopen(mem_file_name, "rb");
if (!mem_file) {
_inst->fatal((char*)"Cannot open file \"%s\" for reading.", mem_file_name);
return; // NOTE: probably not actually needed, but we put it here so VS won't complain
}
fseek(mem_file, _inst->getinitval((char*)"BASE"), SEEK_SET); // seek to base address
size_t inc = 1ULL << _inst->getinitval((char*)"SHIFT", 0);; // get address shift and convert to increment
size_t read = 0; // number of bytes read
if (inc == 1) read = fread(_memory, size, 1, mem_file); // linear read - issue a single fread
else {
/* non-linear read */
for (; read < size; read++) {
if (!fread(&_memory[read], 1, 1, mem_file)) break; // end of file reached
fseek(mem_file, (long)inc - 1, SEEK_CUR); // skip bytes
}
}
_inst->log((char*)"Read %lu bytes from \"%s\".", read, mem_file_name);
fclose(mem_file);
}
/* create memory view popup */
//char* id = _inst->id(); // get part name
//size_t caption_len = 18 + strlen(id) + 1; // "Memory Contents - " + id + null termination
//_mempopup_caption = new char[caption_len]; snprintf(_mempopup_caption, caption_len, "Memory Contents - %s", id);
CREATEPOPUPSTRUCT cps = {
/* id */ 0,
/* type */ PWT_MEMORY,
/* caption */ (char*)"Memory Contents",
/* width */ 16, // width and height are in bytes displayed
/* height */ 16,
/* flags */ PWF_HIDEONANIMATE | PWF_AUTOREFRESH | PWF_SIZEABLE
};
_mempopup = (IMEMORYPOPUP*)_inst->createpopup(&cps);
_mempopup->setmemory(0, _memory, size); // set up memory buffer for popup
}
DsimModel::~DsimModel() {
if (_memory) delete _memory; // deallocate memory
//if (_mempopup_caption) delete _mempopup_caption;
}
VOID DsimModel::runctrl(RUNMODES mode) {
}
VOID DsimModel::actuate(REALTIME time, ACTIVESTATE newstate) {
}
BOOL DsimModel::indicate(REALTIME time, ACTIVEDATA* data) {
return FALSE;
}
/* fixed isdefined (for SUD and whatnot) */
inline BOOL isundefined(STATE s) {
return (s & SP_MASK) == SP_UNDEFINED;
}
VOID DsimModel::simulate(ABSTIME time, DSIMMODES mode) {
// if (mode == DSIMSETTLE) return; // ignore settling phase
//if (mode == DSIMBOOT) {
// float_data(time);
// return;
//}
STATE ce = _ce_pin->istate();
STATE oe = _oe_pin->istate();
STATE we = (_we_pin) ? _we_pin->istate() : SHI; // default to high (no writing) if WE pin doesn't exist (ie. ROM)
uintptr_t addr = get_address();
if (isundefined(ce) || isundefined(oe) || isundefined(we) || isfloating(ce) || ishigh(ce) || isfloating(oe) || isfloating(we) || ishigh(oe) == ishigh(we)/* || addr == UINTPTR_MAX*/) {
/* chip not selected for reading/writing or is in undefined state - go Hi-Z and ignore */
float_data(time);
return;
}
if (!ishigh(we)) {
/* write */
size_t data = get_data();
/*if (data != SIZE_MAX)*/ _memory[addr] = (uint8_t)data;
}
else {
/* read */
set_data(time, _memory[addr]);
}
}
VOID DsimModel::callback(ABSTIME time, EVENTID eventid) {
}
uintptr_t DsimModel::get_address() {
uintptr_t result = 0;
size_t bits = _addr_pins.size();
for (size_t i = 0; i < bits; i++) {
STATE state = _addr_pins[i]->istate();
//if (isfloating(state)) return UINTPTR_MAX;
if (ishigh(state)) result |= (1ULL << i);
}
return result;
}
size_t DsimModel::get_data() {
size_t result = 0;
for (size_t i = 0; i < 8; i++) {
STATE state = _data_pins[i]->istate();
//if (isfloating(state)) return SIZE_MAX;
if (ishigh(state)) result |= (1ULL << i);
}
return result;
}
void DsimModel::set_data(ABSTIME time, uint8_t data) {
for (size_t i = 0; i < 8; i++, data >>= 1) _data_pins[i]->setstate(time, 1, (data & 1) ? SHI : SLO);
}
void DsimModel::float_data(ABSTIME time) {
for (int i = 0; i < 8; i++) _data_pins[i]->setstate(time, 1, FLT);
}