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 #ifndef SRC_REGISTERS_H_
22 #define SRC_REGISTERS_H_
23 
24 #include <glib.h>
25 
26 class Expression;
27 class Processor;
28 class Module;
29 
30 #include "gpsim_classes.h"
31 #include "gpsim_object.h"
32 #include "value.h"
33 #include "ValueCollections.h"
34 
35 #include <string>
36 #include <vector>
37 
38 #define AN_INVALID_ADDRESS 0xffffffff
39 
40 //---------------------------------------------------------
41 // RegisterValue class
42 //
43 // This class is used to represent the value of registers.
44 // It also defines which bits have been initialized and which
45 // are valid.
46 //
47 
48 class RegisterValue {
49 public:
50   unsigned int data = 0;  // The actual numeric value of the register.
51   unsigned int init = 0xff;  // bit mask of initialized bits.
52                              // assume 8-bit wide, uninitialized registers
53 
RegisterValue()54   RegisterValue()
55   {
56   }
57 
RegisterValue(unsigned int d,unsigned int i)58   RegisterValue(unsigned int d, unsigned int i)
59     : data(d), init(i)
60   {
61   }
62 
RegisterValue(const RegisterValue & value)63   RegisterValue(const RegisterValue &value)
64     : data(value.data), init(value.init)
65   {
66   }
67 
initialized()68   inline bool initialized()
69   {
70     return init == 0;
71   }
72 
get()73   inline unsigned int get()
74   {
75     return data;
76   }
77 
put(unsigned int d)78   inline void put(unsigned int d)
79   {
80     data = d;
81   }
82 
put(unsigned int d,unsigned int i)83   inline void put(unsigned int d, unsigned int i)
84   {
85     data = d;
86     init = i;
87   }
88 
geti()89   inline unsigned int geti()
90   {
91     return init;
92   }
93 
puti(unsigned int i)94   inline void puti(unsigned int i)
95   {
96     init = i;
97   }
98 
99   inline void operator = (RegisterValue rv)
100   {
101     data = rv.data;
102     init = rv.init;
103   }
104 
105   inline operator unsigned int ()
106   {
107     return data;
108   }
109 
110   inline operator int ()
111   {
112     return (int)data;
113   }
114 
115   bool operator == (const RegisterValue &rv) const
116   {
117     return data == rv.data && init == rv.init;
118   }
119 
120   bool operator != (const RegisterValue &rv) const
121   {
122     return data != rv.data || init != rv.init;
123   }
124 
125   void operator >>= (unsigned int val)
126   {
127     data >>= val;
128     init >>= val;
129   }
130   char * toString(char *str, int len, int regsize = 2) const;
131   char * toBitStr(char *s, int len, unsigned int BitPos,
132                   const char *ByteSeparator = "_",
133                   const char *HiBitNames = nullptr,
134                   const char *LoBitNames = nullptr,
135                   const char *UndefBitNames = nullptr) const;
136 };
137 
138 
139 //---------------------------------------------------------
140 /// Register - base class for gpsim registers.
141 /// The Register class is used by processors and modules to
142 /// to create memory maps and special function registers.
143 ///
144 
145 class Register : public Value {
146 public:
147   enum REGISTER_TYPES {
148     INVALID_REGISTER,
149     GENERIC_REGISTER,
150     FILE_REGISTER,
151     SFR_REGISTER,
152     BP_REGISTER
153   };
154 
155   RegisterValue value;
156   unsigned int address = AN_INVALID_ADDRESS;
157 
158   // If non-zero, the alias_mask describes all address at which
159   // this file register appears. The assumption (that is true so
160   // far for all pic architectures) is that the aliased register
161   // locations differ by one bit. For example, the status register
162   // appears at addresses 0x03 and 0x83 in the 14-bit core.
163   // Consequently, alias_mask = 0x80 and address (above) is equal
164   // to 0x03.
165 
166   unsigned int alias_mask = 0;
167   RegisterValue por_value;  // power on reset value
168   unsigned int mValidBits = 0xFF;  // = 255 for 8-bit registers, = 65535 for 16-bit registers.
169 
170   // The read_trace and write_trace variables are used while
171   // tracing register reads and writes. Essentially, these are
172   // the trace commands.
173 
174   RegisterValue write_trace;
175   RegisterValue read_trace;
176 
177   // The trace_state is used to reconstruct the state of the
178   // register while traversing a trace buffer.
179 
180   RegisterValue trace_state;
181 
182   guint64 read_access_count = 0;
183   guint64 write_access_count = 0;
184 
185 
186 public:
187   Register(Module *, const char *pName, const char *pDesc = nullptr);
188   virtual ~Register();
189 
190 
191   virtual int set_break(ObjectBreakTypes bt = eBreakAny,
192                         ObjectActionTypes at = eActionHalt,
193                         Expression *expr = nullptr);
194   virtual int clear_break();
195 
196   /// get - method for accessing the register's contents.
197 
198   virtual unsigned int get();
199 
200   /// put - method for writing a new value to the register.
201 
202   virtual void put(unsigned int new_value);
203 
204 
205   /// put_value - is the same as put(), but some extra stuff like
206   /// interfacing to the gui is done. (It's more efficient than
207   /// burdening the run time performance with (unnecessary) gui
208   ///  calls.)
209 
210 
211   virtual void put_value(unsigned int new_value);
212 
213   /// get_value - same as get(), but no trace is performed
214 
get_value()215   virtual unsigned int get_value()
216   {
217     return value.get();
218   }
219 
220   /// getRV - get the whole register value - including the info
221   /// of the three-state bits.
222 
getRV()223   virtual RegisterValue getRV()
224   {
225     value.data = get();
226     return value;
227   }
228 
229   /// putRV - write a new value to the register.
230   /// \deprecated {use SimPutAsRegisterValue()}
231   ///
232 
putRV(RegisterValue rv)233   virtual void putRV(RegisterValue rv)
234   {
235     value.init = rv.init;
236     put(rv.data);
237   }
238 
239   /// getRV_notrace and putRV_notrace are analogous to getRV and putRV
240   /// except that the action (in the derived classes) will not be
241   /// traced. The primary reason for this is to allow the gui to
242   /// refresh it's windows without having the side effect of filling
243   /// up the trace buffer
244 
getRV_notrace()245   virtual RegisterValue getRV_notrace()
246   {
247     value.data = value.get();
248     return value;
249   }
putRV_notrace(RegisterValue rv)250   virtual void putRV_notrace(RegisterValue rv)
251   {
252     value.init = rv.init;
253     put_value(rv.data);
254   }
255 
getRVN()256   virtual RegisterValue getRVN()
257   {
258     return getRVN_notrace();
259   }
getRVN_notrace()260   virtual RegisterValue getRVN_notrace()
261   {
262     return getRV_notrace();
263   }
264 
265   /// set --- cast another Value object type into a register type
266   /// this is used primarily by expression and stimuli processing
267   /// (the put() methods are used by the processors).
268   /// FIXME -- consolidate the get, set, and put methods
269   virtual void set(Value *);
270 
271   /// copy --- This is used during expression parsing.
272   virtual Value *copy();
273 
274   /// get(gint64 &i) --- ugh.
275   virtual void get(gint64 &i);
276 
initialize()277   virtual void initialize()
278   {
279   }
280 
281   /// get3StateBit - returns the 3-state value of a bit
282   /// if a bit is known then a '1' or '0' is returned else,
283   /// a '?' is returned. No check is performed to ensure
284   /// that only a single bit is checked, thus it's possible
285   /// to get the state of a group of bits using this method.
286 
get3StateBit(unsigned int bitMask)287   virtual char get3StateBit(unsigned int bitMask)
288   {
289     RegisterValue rv = getRV_notrace();
290     return (rv.init & bitMask) ? '?' : ((rv.data & bitMask) ? '1' : '0');
291   }
292   /// In the Register class, the 'Register *get()' returns a
293   /// pointer to itself. Derived classes may return something
294   /// else (e.g. a break point may be pointing to the register
295   /// it replaced and will return that instead).
296 
getReg()297   virtual Register *getReg()
298   {
299     return this;
300   }
301 
isa()302   virtual REGISTER_TYPES isa()
303   {
304     return GENERIC_REGISTER;
305   }
reset(RESET_TYPE)306   virtual void reset(RESET_TYPE )
307   {
308   }
309 
310   /// The setbit function is not really intended for general purpose
311   /// registers. Instead, it is a place holder which is over-ridden
312   /// by the IO ports.
313 
314   virtual void setbit(unsigned int bit_number, bool new_value);
315 
316   ///  like setbit, getbit is used mainly for breakpoints.
317 
318   virtual bool get_bit(unsigned int bit_number);
319   virtual double get_bit_voltage(unsigned int bit_number);
320 
321   ///  Breakpoint objects will overload this function and return true.
322 
hasBreak()323   virtual bool hasBreak()
324   {
325     return false;
326   }
327 
328   ///  register_size returns the number of bytes required to store the register
329   ///  (this is used primarily by the gui to determine how wide to make text fields)
330 
331   virtual unsigned int register_size() const;
332 
333   /*
334     When the register is accessed, this action is recorded in the trace buffer.
335     Here we can specify the exact trace command to use.
336    */
337   virtual void set_write_trace(RegisterValue &rv);
338   virtual void set_read_trace(RegisterValue &rv);
put_trace_state(RegisterValue rv)339   virtual void put_trace_state(RegisterValue rv)
340   {
341     trace_state = rv;
342   }
343 
get_trace_state()344   virtual RegisterValue get_trace_state()
345   {
346     return trace_state;
347   }
348 
349   /*
350     convert value to a string:
351    */
352   virtual char * toString(char *str, int len);
353   virtual char * toBitStr(char *s, int len);
baseName()354   virtual std::string &baseName()
355   {
356     return name_str;
357   }
358 
getAddress()359   virtual unsigned int getAddress()
360   {
361     return address;
362   }
setAddress(unsigned int addr)363   virtual void setAddress(unsigned int addr)
364   {
365     address = addr;
366   }
getReplaced()367   Register *getReplaced()
368   {
369     return m_replaced;
370   }
setReplaced(Register * preg)371   void setReplaced(Register *preg)
372   {
373     m_replaced = preg;
374   }
375 
376   virtual void new_name(std::string &);
377   virtual void new_name(const char *);
378 
379 protected:
380   // A pointer to the register that this register replaces.
381   // This is used primarily by the breakpoint code.
382   Register *m_replaced = nullptr;
383 };
384 
385 
386 //---------------------------------------------------------
387 // define a special 'invalid' register class. Accessess to
388 // to this class' value get 0
389 
390 class InvalidRegister : public Register {
391 public:
392   InvalidRegister(Processor *, const char *pName, const char *pDesc = nullptr);
393 
394   void put(unsigned int new_value);
395   unsigned int get();
isa()396   virtual REGISTER_TYPES isa() override
397   {
398     return INVALID_REGISTER;
399   }
getReg()400   virtual Register *getReg() override
401   {
402     return nullptr;
403   }
404 };
405 
406 
407 //---------------------------------------------------------
408 // Base class for a special function register.
409 class BitSink;
410 
411 
412 class sfr_register : public Register {
413 public:
414   sfr_register(Module *, const char *pName, const char *pDesc = nullptr);
415 
416   RegisterValue wdtr_value; // wdt or mclr reset value
417 
isa()418   virtual REGISTER_TYPES isa() override
419   {
420     return SFR_REGISTER;
421   }
initialize()422   virtual void initialize() override {}
423 
424   virtual void reset(RESET_TYPE r) override;
425 
426   // The assign and release BitSink methods don't do anything
427   // unless derived classes redefine them. Their intent is to
428   // provide an interface to the BitSink design - a design that
429   // allows clients to be notified when bits change states.
430 
assignBitSink(unsigned int,BitSink *)431   virtual bool assignBitSink(unsigned int /* bitPosition */ , BitSink *)
432   {
433     return false;
434   }
releaseBitSink(unsigned int,BitSink *)435   virtual bool releaseBitSink(unsigned int /* bitPosition */ , BitSink *)
436   {
437     return false;
438   }
439 };
440 
441 
442 
443 //---------------------------------------------------------
444 // Program Counter
445 //
446 class PCTraceType;
447 class Program_Counter : public Value {
448 public:
449   unsigned int value;              // pc's current value
450   unsigned int memory_size;
451   unsigned int pclath_mask;        // pclath confines PC to banks
452   unsigned int instruction_phase;
453   unsigned int trace_state;        // used while reconstructing the trace history
454 
455   // Trace commands
456   unsigned int trace_increment;
457   unsigned int trace_branch;
458   unsigned int trace_skip;
459   unsigned int trace_other;
460 
461   Program_Counter(const char *name, const char *desc, Module *pM);
462   ~Program_Counter();
463 
464   virtual void increment();
465   virtual void start_skip();
466   virtual void skip();
467   virtual void jump(unsigned int new_value);
468   virtual void interrupt(unsigned int new_value);
469   virtual void computed_goto(unsigned int new_value);
470   virtual void new_address(unsigned int new_value);
471   virtual void put_value(unsigned int new_value);
472   virtual void update_pcl();
473   virtual void get(char *buffer, int buf_size);
get_value()474   virtual unsigned int get_value()
475   {
476     return value;
477   }
get_PC()478   virtual unsigned int get_PC()
479   {
480     return value;
481   }
482 
set_PC(unsigned int new_value)483   virtual void set_PC(unsigned int new_value)
484   {
485     value = new_value;
486     this->update();
487   }
488 
489   /// set --- cast another Value object type into a program counter register type
490   /// this is used primarily by expression and stimuli processing
491   /// (the put() methods are used by the processors).
492   /// FIXME -- consolidate the get, set, and put methods
493   virtual void set(Value *);
494 
495   // initialize the dynamically allocated trace type
496   virtual void set_trace_command();
497 
498   /// get_raw_value -- on the 16-bit cores, get_value is multiplied by 2
499   /// whereas get_raw_value isn't. The raw value of the program counter
500   /// is used as an index into the program memory.
get_raw_value()501   virtual unsigned int get_raw_value()
502   {
503     return value;
504   }
505 
set_phase(int phase)506   virtual void set_phase(int phase)
507   {
508     instruction_phase = phase;
509   }
get_phase()510   virtual int get_phase()
511   {
512     return instruction_phase;
513   }
514 
set_reset_address(unsigned int _reset_address)515   void set_reset_address(unsigned int _reset_address)
516   {
517     reset_address = _reset_address;
518   }
get_reset_address()519   unsigned int get_reset_address()
520   {
521     return reset_address;
522   }
523 
524   void reset();
525 
526   virtual unsigned int get_next();
527 
put_trace_state(unsigned int ts)528   virtual void put_trace_state(unsigned int ts)
529   {
530     trace_state = ts;
531   }
532 
533 protected:
534   unsigned int reset_address;      /* Value pc gets at reset */
535   PCTraceType *m_pPCTraceType;
536 };
537 
538 
539 // Used in the command prompt interface
540 class RegisterCollection : public IIndexedCollection {
541 public:
542   RegisterCollection(Processor *pProcessor,
543                      const char *collection_name,
544                      Register   **ppRegisters,
545                      unsigned int uiSize);
546   ~RegisterCollection();
547 
548   virtual void get(char *return_str, int len);
549   virtual unsigned int GetSize();
550   virtual Value &GetAt(unsigned int uIndex, Value *pValue = nullptr);
551   virtual void SetAt(unsigned int uIndex, Value *pValue);
552   virtual void ConsolidateValues(int &iColumnWidth,
553                                  std::vector<std::string> &aList,
554                                  std::vector<std::string> &aValue);
555   //  virtual void SetAt(ExprList_t* pIndexers, Expression *pExpr);
556   virtual unsigned int GetLowerBound();
557   virtual unsigned int GetUpperBound();
558 
559 private:
560   Processor *   m_pProcessor;
561   Register **   m_ppRegisters;
562   unsigned int  m_uSize;
563   Integer       m_ReturnValue;
564 };
565 
566 
567 //------------------------------------------------------------------------
568 // BitSink
569 //
570 // A BitSink is an object that can direct bit changes in an SFR to some
571 // place where they're needed. The purpose is to abstract the interface
572 // between special bits and the various peripherals.
573 //
574 // A client wishing to be notified whenever an SFR bit changes states
575 // will create a BitSink object and pass its pointer to the SFR. The
576 // client will also tell the SFR which bit this applies to. Now, when
577 // the bit changes states in the SFR, the SFR will call the setSink()
578 // method.
579 
580 class BitSink {
581 public:
~BitSink()582   virtual ~BitSink()
583   {
584   }
585 
586   virtual void setSink(bool) = 0;
587 };
588 
589 
590 #endif // SRC_REGISTERS_H_
591