1 /*
2 Copyright (C) 1998-2003 Scott Dattalo
3
4 This file is part of the libgpsim library of gpsim
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, see
18 <http://www.gnu.org/licenses/lgpl-2.1.html>.
19 */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <cstring>
26 #include <algorithm>
27 #include <iostream>
28 #include <sstream>
29
30 #include "../config.h"
31 #include "breakpoints.h"
32 #include "processor.h"
33 #include "registers.h"
34 #include "trace.h"
35
count_bits(unsigned int ui)36 unsigned int count_bits(unsigned int ui)
37 {
38 unsigned int bits = 0;
39
40 while (ui) {
41 ui &= (ui - 1);
42 bits++;
43 }
44
45 return bits;
46 }
47
48
49 //========================================================================
50 // toString
51 //
52 // Convert a RegisterValue type to a string.
53 //
54 // A RegisterValue type allows the bits of a register to take on three
55 // values: High, Low, or undefined. If all of the bits are defined,
56 // then this routine will convert register value to a hexadecimal string.
57 // Any undefined bits within a nibble will cause the associated nibble to
58 // be undefined and will get converted to a question mark.
59 //
60
toString(char * str,int len,int regsize) const61 char * RegisterValue::toString(char *str, int len, int regsize) const
62 {
63 if (str && len) {
64 RegisterValue rv = *this;
65 char hex2ascii[] = "0123456789ABCDEF";
66 char undefNibble = '?';
67 int i;
68 int m = regsize * 2 + 1;
69
70 if (len < m) {
71 m = len;
72 }
73
74 m--;
75
76 for (i = 0; i < m; i++) {
77 if (rv.init & 0x0f) {
78 str[m - i - 1] = undefNibble;
79
80 } else {
81 str[m - i - 1] = hex2ascii[rv.data & 0x0f];
82 }
83
84 rv.init >>= 4;
85 rv.data >>= 4;
86 }
87
88 str[m] = '\0';
89 }
90
91 return str;
92 }
93
94
95 //========================================================================
96 // SplitBitString
97 //
98 // The purpose of this routine is to convert a string of bitnames into
99 // an array of names. The string is formatted like:
100 //
101 // b1.b2.b3
102 //
103 // In other words, a period is the delimeter between the names.
104 // This gets converted to:
105 //
106 // b1
107 // b2
108 // b2
109 //
110 // INPUTS
111 // n - number of names
112 // in - input string formatted as described
113 // in2 - if 'in' is NULL, then all 'n' names will be 'in2'
114 //
115 // OUTPUTS
116 // out - an array to hold the strings.
117 //
118 // Note, the input string 'in' will be modified such that all of the '.'s will
119 // get turned into string terminating 0's.
120 //
121
SplitBitString(int n,const char ** out,char * in,const char * in2)122 static void SplitBitString(int n, const char **out, char *in, const char *in2)
123 {
124 if (!in) {
125 for (int i = 0; i < n; i++) {
126 out[i] = in2;
127 }
128
129 } else {
130 char *str = in;
131
132 for (int i = 0; i < n; i++) {
133 out[i] = in;
134 str = strchr(in, '.');
135
136 if (str) {
137 *str = '\0';
138 in = ++str;
139 }
140
141 //cout << "split :" << i << " ==> " << out[i] << endl;
142 }
143 }
144 }
145
146
147 //========================================================================
148 // toBitStr
149 //
150 // Convert a RegisterValue type to a bit string
151 //
152 // Given a pointer to a string, this function will convert a register
153 // value into a string of ASCII characters. If no names are given
154 // for the bits, then the default values of 'H', 'L', and '?' are
155 // used for high, low and undefined.
156 //
157 // The input 'BitPos' is a bit mask that has a bit set for each bit that
158 // the user wishes to display.
159 //
160
toBitStr(char * s,int len,unsigned int BitPos,const char * cByteSeparator,const char * HiBitNames,const char * LoBitNames,const char * UndefBitNames) const161 char * RegisterValue::toBitStr(char *s, int len, unsigned int BitPos,
162 const char *cByteSeparator,
163 const char *HiBitNames,
164 const char *LoBitNames,
165 const char *UndefBitNames) const
166 {
167 unsigned int i, mask;
168 const unsigned int max = 32;
169
170 if (!s || len <= 0) {
171 return nullptr;
172 }
173
174 unsigned int nBits = count_bits(BitPos);
175
176 if (nBits >= max) {
177 nBits = max;
178 }
179
180 const char *HiNames[32];
181 const char *LoNames[32];
182 const char *UndefNames[32];
183 char *cHi = HiBitNames ? strdup(HiBitNames) : nullptr;
184 char *cLo = LoBitNames ? strdup(LoBitNames) : nullptr;
185 char *cUn = UndefBitNames ? strdup(UndefBitNames) : nullptr;
186 SplitBitString(nBits, HiNames, cHi, "1");
187 SplitBitString(nBits, LoNames, cLo, "0");
188 SplitBitString(nBits, UndefNames, cUn, "?");
189 char *dest = s;
190 int bitNumber = 31;
191
192 for (i = 0, mask = 1 << 31; mask; mask >>= 1, bitNumber--) {
193 if (BitPos & mask) {
194 const char *H = HiNames[i];
195 const char *L = LoNames[i];
196 const char *U = UndefNames[i];
197 const char *c = (init & mask) ? U :
198 ((data & mask) ? H : L);
199 strncpy(dest, c, len);
200 int l = strlen(c);
201 len -= l;
202 dest += l;
203 *dest = '\0';
204
205 if (i++ > nBits || len < 0) {
206 break;
207 }
208
209 if (cByteSeparator && bitNumber && ((bitNumber % 8) == 0)) {
210 strncpy(dest, cByteSeparator, len);
211 int l = strlen(cByteSeparator);
212 len -= l;
213 dest += l;
214 *dest = '\0';
215
216 if (len < 0) {
217 break;
218 }
219 }
220 }
221 }
222
223 free(cHi);
224 free(cLo);
225 free(cUn);
226 return s;
227 }
228
229
230 //--------------------------------------------------
231 // Member functions for the file_register base class
232 //--------------------------------------------------
233 //
234 // For now, initialize the register with valid data and set that data equal to 0.
235 // Eventually, the initial value will be marked as 'uninitialized.
236
Register(Module * _cpu,const char * pName,const char * pDesc)237 Register::Register(Module *_cpu, const char *pName, const char *pDesc)
238 : Value(pName, pDesc, _cpu), value(RegisterValue(0, 0)),
239 por_value(RegisterValue(0, 0))
240 {
241 set_xref(new XrefObject(this));
242 }
243
244
~Register()245 Register::~Register()
246 {
247 if (cpu) {
248 //cout << "Removing register from ST:" << name_str << " addr "<< this << endl;
249 cpu->removeSymbol(this);
250 }
251 }
252
253
254 //------------------------------------------------------------
set_break(ObjectBreakTypes bt,ObjectActionTypes at,Expression * expr)255 int Register::set_break(ObjectBreakTypes bt, ObjectActionTypes at, Expression *expr)
256 {
257 return get_bp().set_break(bt, at, this, expr);
258 }
259
260
clear_break()261 int Register::clear_break()
262 {
263 return -1;
264 }
265
266
267 //------------------------------------------------------------
268 // get()
269 //
270 // Return the contents of the file register.
271 // (note - breakpoints on file register reads
272 // are not checked here. Instead, a breakpoint
273 // object replaces those instances of file
274 // registers for which we wish to monitor.
275 // So a file_register::get call will invoke
276 // the breakpoint::get member function. Depending
277 // on the type of break point, this get() may
278 // or may not get called).
279
get()280 unsigned int Register::get()
281 {
282 trace.raw(read_trace.get() | value.get());
283 return value.get();
284 }
285
286
287 //------------------------------------------------------------
288 // put()
289 //
290 // Update the contents of the register.
291 // See the comment above in file_register::get()
292 // with respect to break points
293 //
294
put(unsigned int new_value)295 void Register::put(unsigned int new_value)
296 {
297 trace.raw(write_trace.get() | value.get());
298 value.put(new_value);
299 }
300
301
get_bit(unsigned int bit_number)302 bool Register::get_bit(unsigned int bit_number)
303 {
304 return (value.get() & (1 << bit_number)) ? true : false;
305 }
306
307
get_bit_voltage(unsigned int bit_number)308 double Register::get_bit_voltage(unsigned int bit_number)
309 {
310 return get_bit(bit_number) ? 5.0 : 0.0;
311 }
312
313
314 //--------------------------------------------------
315 // set_bit
316 //
317 // set a single bit in a register. Note that this
318 // is really not intended to be used on the file_register
319 // class. Instead, setbit is a place holder for high level
320 // classes that overide this function
setbit(unsigned int bit_number,bool new_value)321 void Register::setbit(unsigned int bit_number, bool new_value)
322 {
323 int set_mask = (1 << bit_number);
324
325 if (set_mask & mValidBits) {
326 trace.raw(write_trace.get() | value.get());
327 value.put((value.get() & ~set_mask) | (new_value ? set_mask : 0));
328 }
329 }
330
331
332 //-----------------------------------------------------------
333 // void Register::put_value(unsigned int new_value)
334 //
335 // put_value is used by the gui to change the contents of
336 // file registers. We could've let the gui use the normal
337 // 'put' member function to change the contents, however
338 // there are instances where 'put' has a cascading affect.
339 // For example, changing the value of an i/o port's tris
340 // could cause i/o pins to change states. In these cases,
341 // we'd like the gui to be notified of all of the cascaded
342 // changes. So rather than burden the real-time simulation
343 // with notifying the gui, I decided to create the 'put_value'
344 // function instead.
345 // Since this is a virtual function, derived classes have
346 // the option to override the default behavior.
347 //
348 // inputs:
349 // unsigned int new_value - The new value that's to be
350 // written to this register
351 // returns:
352 // nothing
353 //
354 //-----------------------------------------------------------
355
put_value(unsigned int new_value)356 void Register::put_value(unsigned int new_value)
357 {
358 // go ahead and use the regular put to write the data.
359 // note that this is a 'virtual' function. Consequently,
360 // all objects derived from a file_register should
361 // automagically be correctly updated.
362 value.put(new_value);
363
364 // Even though we just wrote a value to this register,
365 // it's possible that the register did not get fully
366 // updated (e.g. porta on many pics has only 5 valid
367 // pins, so the upper three bits of a write are meaningless)
368 // So we should explicitly tell the gui (if it's
369 // present) to update its display.
370 update();
371 }
372
373
374 ///
375 /// New accessor functions
376 //////////////////////////////////////////////////////////////
377
register_size() const378 unsigned int Register::register_size() const
379 {
380 Processor *pProc = Value::get_cpu();
381 return pProc ? pProc->register_size() : 1;
382 }
383
384
385 //-----------------------------------------------------------
386 // set_write_trace
387 // set_read_trace
388 //
389 // These functions initialize the trace type to be used for
390 // register reads and writes.
391 //
set_write_trace(RegisterValue & rv)392 void Register::set_write_trace(RegisterValue &rv)
393 {
394 write_trace = rv;
395 }
396
397
set_read_trace(RegisterValue & rv)398 void Register::set_read_trace(RegisterValue &rv)
399 {
400 read_trace = rv;
401 }
402
403
404 //------------------------------------------------------------
405
toString(char * str,int len)406 char * Register::toString(char *str, int len)
407 {
408 return getRV_notrace().toString(str, len, register_size() * 2);
409 }
410
411
toBitStr(char * s,int len)412 char * Register::toBitStr(char *s, int len)
413 {
414 unsigned int bit_length = register_size() * 8;
415 unsigned int bits = (1 << bit_length) - 1;
416 return getRV_notrace().toBitStr(s, len, bits);
417 }
418
419
420 //-----------------------------------------------------------
421
new_name(const char * s)422 void Register::new_name(const char *s)
423 {
424 if (s) {
425 std::string str = s;
426 new_name(str);
427 }
428 }
429
430
new_name(std::string & new_name)431 void Register::new_name(std::string &new_name)
432 {
433 if (name_str != new_name) {
434 if (name_str.empty()) {
435 name_str = new_name;
436 return;
437 }
438
439 name_str = new_name;
440
441 if (cpu) {
442 addName(new_name);
443 cpu->addSymbol(this, &new_name);
444 }
445 }
446 }
447
448
449 //------------------------------------------------------------------------
450 // set -- assgin the value of some other object to this Register
451 //
452 // This is used (primarily) during Register stimuli processing. If
453 // a register stimulus is attached to this register, then it will
454 // call ::set() and supply a Value pointer.
455
set(Value * pVal)456 void Register::set(Value * pVal)
457 {
458 Register *pReg = dynamic_cast<Register *>(pVal);
459
460 if (pReg) {
461 putRV(pReg->getRV());
462 return;
463 }
464
465 if (pVal) {
466 put_value((unsigned int)*pVal);
467 }
468 }
469
470
471 //------------------------------------------------------------------------
472 // copy - create a new Value object that's a 'copy' of this object
473 //
474 // We really don't perform a true copy. Instead, an Integer object
475 // is created containing the same numeric value of this object.
476 // This code is called during expression parsing. *NOTE* this copied
477 // object can be assigned a new value, however that value will not
478 // propagate to the Register!
479
copy()480 Value *Register::copy()
481 {
482 Value *val = new ValueWrapper(this);
483 return val;
484 }
485
486
get(gint64 & i)487 void Register::get(gint64 &i)
488 {
489 i = get_value();
490 }
491
492
493 //--------------------------------------------------
494 //--------------------------------------------------
495 //--------------------------------------------------
sfr_register(Module * pCpu,const char * pName,const char * pDesc)496 sfr_register::sfr_register(Module *pCpu, const char *pName, const char *pDesc)
497 : Register(pCpu, pName, pDesc), wdtr_value(0, 0xff)
498 {
499 }
500
501
reset(RESET_TYPE r)502 void sfr_register::reset(RESET_TYPE r)
503 {
504 switch (r) {
505 case POR_RESET:
506 putRV(por_value);
507 break;
508
509 default:
510
511 // Most registers simply retain their value across WDT resets.
512 if (wdtr_value.initialized()) {
513 putRV(wdtr_value);
514 }
515
516 break;
517 }
518 }
519
520
521 //--------------------------------------------------
522 //--------------------------------------------------
523
524 //--------------------------------------------------
525 // member functions for the InvalidRegister class
526 //--------------------------------------------------
put(unsigned int new_value)527 void InvalidRegister::put(unsigned int new_value)
528 {
529 std::cout << "attempt write to invalid file register\n";
530
531 if (address != AN_INVALID_ADDRESS) {
532 std::cout << " address 0x" << std::hex << address << ',';
533 }
534
535 std::cout << " value 0x" << std::hex << new_value << '\n';
536
537 if (((Processor*)cpu)->getBreakOnInvalidRegisterWrite()) {
538 bp.halt();
539 }
540
541 trace.raw(write_trace.get() | value.get());
542 }
543
544
get()545 unsigned int InvalidRegister::get()
546 {
547 std::cout << "attempt read from invalid file register\n";
548
549 if (address != AN_INVALID_ADDRESS) {
550 std::cout << " address 0x" << std::hex << address << '\n';
551 }
552
553 trace.raw(read_trace.get() | value.get());
554
555 if (((Processor*)cpu)->getBreakOnInvalidRegisterRead()) {
556 bp.halt();
557 }
558
559 return 0;
560 }
561
562
InvalidRegister(Processor * pCpu,const char * pName,const char * pDesc)563 InvalidRegister::InvalidRegister(Processor *pCpu, const char *pName, const char *pDesc)
564 : Register(pCpu, pName, pDesc)
565 {
566 }
567
568
RegisterCollection(Processor * pProcessor,const char * pC_collection_name,Register ** ppRegisters,unsigned int uiSize)569 RegisterCollection::RegisterCollection(Processor *pProcessor,
570 const char *pC_collection_name,
571 Register **ppRegisters,
572 unsigned int uiSize)
573 : IIndexedCollection(16), m_pProcessor(pProcessor), m_ppRegisters(ppRegisters),
574 m_uSize(uiSize), m_ReturnValue(0)
575 {
576 gpsimObject::new_name(pC_collection_name);
577 pProcessor->addSymbol(this);
578 }
579
580
~RegisterCollection()581 RegisterCollection:: ~RegisterCollection()
582 {
583 if (m_pProcessor) {
584 m_pProcessor->removeSymbol(this);
585 }
586 }
587
588
589 // Displays in symbol GUI
get(char * return_str,int len)590 void RegisterCollection::get(char *return_str, int len)
591 {
592 if (return_str) {
593 strncpy(return_str, "", len);
594 }
595 }
596
597
GetSize()598 unsigned int RegisterCollection::GetSize()
599 {
600 return m_uSize;
601 }
602
603
GetAt(unsigned int uIndex,Value *)604 Value &RegisterCollection::GetAt(unsigned int uIndex, Value *)
605 {
606 if (uIndex > m_uSize) {
607 throw Error("index is out of range");
608 }
609
610 m_ReturnValue.set((int)m_ppRegisters[uIndex]->get_value());
611 m_ReturnValue.setBitmask(m_pProcessor->register_mask());
612 std::ostringstream sIndex;
613
614 if (m_pProcessor) {
615 sIndex << m_pProcessor->name() << "." ;
616 }
617
618 sIndex << Value::name() << "["
619 << std::hex << m_szPrefix << uIndex << "]" << '\000';
620 m_ReturnValue.new_name(sIndex.str().c_str());
621 return m_ReturnValue;
622 }
623
624
SetAt(unsigned int uIndex,Value * pValue)625 void RegisterCollection::SetAt(unsigned int uIndex, Value *pValue)
626 {
627 if (uIndex > m_uSize) {
628 throw Error("index is out of range");
629 }
630
631 Integer *pInt = dynamic_cast<Integer*>(pValue);
632
633 if (pInt == nullptr) {
634 throw Error("rValue is not an Integer");
635
636 } else {
637 m_ppRegisters[uIndex]->put((unsigned int)(int)*pInt);
638 }
639 }
640
641
ConsolidateValues(int & iColumnWidth,std::vector<std::string> & aList,std::vector<std::string> & aValue)642 void RegisterCollection::ConsolidateValues(int &iColumnWidth,
643 std::vector<std::string> &aList,
644 std::vector<std::string> &aValue)
645 {
646 unsigned int uFirstIndex = 0;
647 unsigned int uIndex;
648 Register * pReg = m_ppRegisters[0];
649 Integer uLastValue(pReg->getRV_notrace().data);
650 uLastValue.setBitmask(m_pProcessor->register_mask());
651
652 for (uIndex = 0; uIndex < m_uSize; uIndex++) {
653 pReg = m_ppRegisters[uIndex];
654 RegisterValue rvValue = pReg->getRV_notrace();
655
656 if ((unsigned int)uLastValue != rvValue.data) {
657 PushValue(uFirstIndex, uIndex, &uLastValue, aList, aValue);
658 iColumnWidth = std::max(iColumnWidth, (int)aList.back().size());
659 uFirstIndex = uIndex;
660 uLastValue = rvValue.data;
661 }
662 }
663
664 uIndex--;
665
666 // Record the last set of elements
667 if (uFirstIndex <= uIndex) {
668 PushValue(uFirstIndex, uIndex, &uLastValue, aList, aValue);
669 iColumnWidth = std::max(iColumnWidth, (int)aList.back().size());
670 }
671 }
672
673
674 //void RegisterCollection::SetAt(ExprList_t* pIndexers, Expression *pExpr) {
675 // throw Error("RegisterCollection::SetAt() not implemented");
676 //}
677
GetLowerBound()678 unsigned int RegisterCollection::GetLowerBound()
679 {
680 return 0;
681 }
682
683
GetUpperBound()684 unsigned int RegisterCollection::GetUpperBound()
685 {
686 return m_uSize - 1;
687 }
688
689
690