1 /*
2    Copyright (C) 2017 Roy R Rankin
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 // CONFIGURABLE LOGIC CELL (CLC)
22 
23 //#define DEBUG
24 #if defined(DEBUG)
25 #include "../config.h"
26 #define Dprintf(arg) {printf("%s:%d ",__FILE__,__LINE__); printf arg; }
27 #else
28 #define Dprintf(arg) {}
29 #endif
30 
31 #include <assert.h>
32 #include <stdio.h>
33 
34 #include "pic-processor.h"
35 #include "gpsim_time.h"
36 #include "clc.h"
37 #include "nco.h"
38 #include "cwg.h"
39 #include "stimuli.h"
40 #include "trace.h"
41 
42 // Report state changes on incoming INx pins
43 class INxSignalSink: public SignalSink
44 {
45 public:
INxSignalSink(CLC_BASE * _clc,int _index)46     INxSignalSink(CLC_BASE * _clc, int _index)
47         : m_clc(_clc), index(_index)
48     {
49     }
50 
setSinkState(char new3State)51     virtual void setSinkState(char new3State)
52     {
53         m_clc->setState(new3State, index);
54     }
release()55     virtual void release()
56     {
57         delete this;
58     }
59 
60 private:
61     CLC_BASE * m_clc;
62     int index;
63 };
64 
65 
66 class CLCSigSource: public SignalControl
67 {
68 public:
CLCSigSource(CLC_BASE * _clc,PinModule * _pin)69     CLCSigSource(CLC_BASE * _clc, PinModule * _pin)
70         : m_clc(_clc), m_pin(_pin), m_state('?')
71     {
72         assert(m_clc);
73     }
~CLCSigSource()74     virtual ~CLCSigSource()
75     {
76     }
77 
setState(char _state)78     void setState(char _state)
79     {
80         m_state = _state;
81     }
getState()82     virtual char getState()
83     {
84         return m_state;
85     }
release()86     virtual void release()
87     {
88         m_clc->releasePinSource(m_pin);
89     }
90 
91 private:
92     CLC_BASE *m_clc;
93     PinModule *m_pin;
94     char m_state;
95 };
96 
97 
put(unsigned int new_value)98 void CLCxCON::put(unsigned int new_value)
99 {
100     new_value &= write_mask;
101     new_value |= (value.get() & ~write_mask);
102     unsigned int diff = new_value ^ value.get();
103     trace.raw(write_trace.get() | value.get());
104     value.put(new_value);
105 
106     if (!diff)
107     {
108         return;
109     }
110 
111     m_clc->update_clccon(diff);
112 }
113 
114 
put(unsigned int new_value)115 void CLCxPOL::put(unsigned int new_value)
116 {
117     new_value &= write_mask;
118     unsigned int diff = new_value ^ value.get();
119     trace.raw(write_trace.get() | value.get());
120     value.put(new_value);
121 
122     if (!diff)
123     {
124         return;
125     }
126 
127     m_clc->compute_gates();
128 }
129 
130 
131 // used when CLC has 4 data select registers (CLCxSEL0-3)
132 // reg_number in range 0-3 to indicate which register
CLCxSELx(CLC_4SEL * _clc,Processor * pCpu,const char * pName,const char * pDesc,unsigned int _reg_number)133 CLCxSELx::CLCxSELx(CLC_4SEL * _clc, Processor * pCpu, const char *pName,
134                    const char *pDesc, unsigned int _reg_number)
135     : sfr_register(pCpu, pName, pDesc), m_clc(_clc), write_mask(0x1f),
136       reg_number(_reg_number)
137 {
138 }
put(unsigned int new_value)139 void CLCxSELx::put(unsigned int new_value)
140 {
141     new_value &= write_mask;
142     trace.raw(write_trace.get() | value.get());
143     unsigned int diff = new_value ^ value.get();
144     value.put(new_value);
145 
146     if(diff)
147     {
148         switch(reg_number)
149         {
150         case 0:
151             m_clc->D1S(new_value);
152             break;
153 
154         case 1:
155             m_clc->D2S(new_value);
156             break;
157 
158         case 2:
159             m_clc->D3S(new_value);
160             break;
161 
162         case 3:
163             m_clc->D4S(new_value);
164             break;
165         }
166 
167         if (m_clc->CLCenabled())
168         {
169             m_clc->config_inputs(true);
170         }
171     }
172 }
173 
CLCxSEL0(CLC * _clc,Processor * pCpu,const char * pName,const char * pDesc)174 CLCxSEL0::CLCxSEL0(CLC * _clc, Processor * pCpu, const char *pName,
175                    const char *pDesc)
176     : sfr_register(pCpu, pName, pDesc), m_clc(_clc), write_mask(0x77)
177 {
178 }
179 
180 
put(unsigned int new_value)181 void CLCxSEL0::put(unsigned int new_value)
182 {
183     new_value &= write_mask;
184     trace.raw(write_trace.get() | value.get());
185     unsigned int diff = new_value ^ value.get();
186     value.put(new_value);
187 
188     if (diff & 0xf)
189     {
190         m_clc->D1S(new_value & 0xf);
191     }
192 
193     if (diff & 0xf0)
194     {
195         m_clc->D2S((new_value & 0xf0) >> 4);
196     }
197 
198     if (diff && m_clc->CLCenabled())
199     {
200         m_clc->config_inputs(true);
201     }
202 }
203 
204 
CLCxSEL1(CLC * _clc,Processor * pCpu,const char * pName,const char * pDesc)205 CLCxSEL1::CLCxSEL1(CLC * _clc, Processor * pCpu, const char *pName,
206                    const char *pDesc)
207     : sfr_register(pCpu, pName, pDesc), m_clc(_clc), write_mask(0x77)
208 {
209 }
210 
211 
put(unsigned int new_value)212 void CLCxSEL1::put(unsigned int new_value)
213 {
214     new_value &= write_mask;
215     trace.raw(write_trace.get() | value.get());
216     unsigned int diff = new_value ^ value.get();
217     value.put(new_value);
218 
219     if (diff & 0xf)
220     {
221         m_clc->D3S(new_value & 0xf);
222     }
223 
224     if (diff & 0xf0)
225     {
226         m_clc->D4S((new_value & 0xf0) >> 4);
227     }
228 
229     if (diff && m_clc->CLCenabled())
230     {
231         m_clc->config_inputs(true);
232     }
233 }
234 
235 
put(unsigned int new_value)236 void CLCxGLS0::put(unsigned int new_value)
237 {
238     unsigned int diff = new_value ^ value.get();
239     trace.raw(write_trace.get() | value.get());
240     value.put(new_value);
241 
242     if (!diff)
243     {
244         return;
245     }
246 
247     if (m_clc->CLCenabled())
248     {
249         m_clc->config_inputs(true);
250     }
251 
252     m_clc->compute_gates();
253 }
254 
255 
put(unsigned int new_value)256 void CLCxGLS1::put(unsigned int new_value)
257 {
258     unsigned int diff = new_value ^ value.get();
259     trace.raw(write_trace.get() | value.get());
260     value.put(new_value);
261 
262     if (!diff)
263     {
264         return;
265     }
266 
267     if (m_clc->CLCenabled())
268     {
269         m_clc->config_inputs(true);
270     }
271 
272     m_clc->compute_gates();
273 }
274 
275 
put(unsigned int new_value)276 void CLCxGLS2::put(unsigned int new_value)
277 {
278     unsigned int diff = new_value ^ value.get();
279     trace.raw(write_trace.get() | value.get());
280     value.put(new_value);
281 
282     if (!diff)
283     {
284         return;
285     }
286 
287     if (m_clc->CLCenabled())
288     {
289         m_clc->config_inputs(true);
290     }
291 
292     m_clc->compute_gates();
293 }
294 
295 
put(unsigned int new_value)296 void CLCxGLS3::put(unsigned int new_value)
297 {
298     unsigned int diff = new_value ^ value.get();
299     trace.raw(write_trace.get() | value.get());
300     value.put(new_value);
301 
302     if (!diff)
303     {
304         return;
305     }
306 
307     if (m_clc->CLCenabled())
308     {
309         m_clc->config_inputs(true);
310     }
311 
312     m_clc->compute_gates();
313 }
314 
315 
316 // CLCx calls to set it's LCx_OUT bit, result shared with
317 // all CLCx instances.
set_bit(bool bit_val,unsigned int pos)318 void CLCDATA::set_bit(bool bit_val, unsigned int pos)
319 {
320     Dprintf(("set_bit LC%u_OUT %d\n", pos + 1, bit_val));
321 
322     if (bit_val)
323     {
324         value.put(value.get() | (1 << pos));
325 
326     }
327     else
328     {
329         value.put(value.get() & ~(1 << pos));
330     }
331 
332     for (int i = 0; i < 4; i++)
333     {
334         if (m_clc[i])
335         {
336             m_clc[i]->lcxupdate(bit_val, pos);
337         }
338     }
339 }
340 
341 
342 // used where all CLC instances use same input pins
setIOpin(PinModule * pin,int data)343 void CLCDATA::setIOpin(PinModule *pin, int data)
344 {
345     for(int i=0; i<4; i++)
346     {
347         if (m_clc[i])
348             m_clc[i]->setIOpin(pin,data);
349     }
350 }
CLC(Processor * cpu,unsigned int _index,CLCDATA * _clcdata)351 CLC::CLC(Processor * cpu, unsigned int _index, CLCDATA * _clcdata):
352     CLC_BASE(cpu, _index, _clcdata),
353     clcxsel0(this, cpu, "clcxsel0", "Multiplexer Data 1 and 2 Select Register"),
354     clcxsel1(this, cpu, "clcxsel1", "Multiplexer Data 3 and 4 Select Register")
355 {
356 }
357 
358 
CLC_BASE(Processor * cpu,unsigned int _index,CLCDATA * _clcdata)359 CLC_BASE::CLC_BASE(Processor * cpu, unsigned int _index, CLCDATA * _clcdata):
360     index(_index),
361     clcxcon(this, cpu, "clcxcon", "Configurable Logic Cell Control Register"),
362     clcxpol(this, cpu, "clcxpol", "Configurable Logic Cell Signal Polarity"),
363     clcxgls0(this, cpu, "clcxgls0", "Gate 1 Logic Select Register"),
364     clcxgls1(this, cpu, "clcxgls1", "Gate 2 Logic Select Register"),
365     clcxgls2(this, cpu, "clcxgls2", "Gate 3 Logic Select Register"),
366     clcxgls3(this, cpu, "clcxgls3", "Gate 4 Logic Select Register"),
367     clcdata(_clcdata)
368 {
369     for (int i = 0; i < 4; i++)
370     {
371         CMxOUT_level[i] = false;
372         pwmx_level[i] = false;
373         lcxdT[i] = false;
374         lcxg[i] = false;
375         dxs_data_length[i] = 0;
376         dxs_data[i] = nullptr;
377         INxsink[i] = nullptr;
378         INxactive[i] = 0;
379         INxstate[i] = false;
380     }
381 
382     std::fill_n(DxS_data, 4, UNUSED);
383     std::fill_n(pinCLCxIN, 4, nullptr);
384 }
385 
386 
~CLC_BASE()387 CLC_BASE::~CLC_BASE()
388 {
389     delete CLCxsrc;
390 }
391 
392 
393 /*
394 **    Set the DxS input selection table
395 **         input - table 1-4
396 **	   length - number of entries in the data array
397 **         data   - array of data_in enums
398 */
set_dxs_data(int input,int length,data_in * data)399 void CLC_BASE::set_dxs_data(int input, int length, data_in *data)
400 {
401     assert(input && input < 5);
402 
403     dxs_data_length[input-1] = length;
404     dxs_data[input-1] = data;
405 #ifdef DEBUG
406     Dprintf(("CLC_BASE::set_dxs_data  CLC%u table %d\n", index+1, input));
407     for(int i=0; i<length; i++)
408         printf("%d, ", dxs_data[input-1][i]);
409     printf("\n");
410 #endif
411 }
412 
setIOpin(PinModule * pin,int data)413 void CLC_BASE::setIOpin(PinModule *pin, int data)
414 {
415     Dprintf(("CLC_BASE::setIOpin CLC%u pin=%s data=%d\n", index+1, pin?pin->getPin().name().c_str():"NULL", data));
416     if (data == CLCout_PIN)
417     {
418         if (!pin)
419             oeCLCx(false);
420         else
421             setCLCxPin(pin);
422     }
423     else if (data >= CLCin0_PIN && data <= CLCin3_PIN)
424     {
425         int i = data - CLCin0_PIN;
426         if (pin != pinCLCxIN[i])
427         {
428             if (CLCenabled())
429             {
430                 if (pinCLCxIN[i])
431                     enableINxpin(i, false);
432                 pinCLCxIN[i] = pin;
433                 enableINxpin(i, true);
434             }
435             else
436             {
437                 pinCLCxIN[i] = pin;
438             }
439         }
440     }
441     else
442     {
443         fprintf(stderr, "CLC_BASE::setIOpin data=%d not supported\n", data);
444     }
445 }
446 
447 
448 // Handle output pin multiplexing
setCLCxPin(PinModule * alt_pin)449 void CLC_BASE::setCLCxPin(PinModule * alt_pin)
450 {
451 
452     if (alt_pin != pinCLCx)
453     {
454         oeCLCx(false);
455         pinCLCx = alt_pin;
456         oeCLCx(true);
457     }
458 }
459 
460 
461 
462 
463 // Handle T0 overflow notification
t0_overflow()464 void CLC_BASE::t0_overflow()
465 {
466     bool gate_change = false;
467 
468     for (int i = 0; i < 4; i++)
469     {
470         if (DxS_data[i] == T0_OVER)
471         {
472             lcxdT[i] = true;
473             gate_change = true;
474         }
475     }
476 
477     if (gate_change)
478     {
479         Dprintf(("CLC%u t0_overflow() enable=%d\n", index + 1,
480                  CLCenabled()));
481         compute_gates();
482 
483         for (int i = 0; i < 4; i++)
484         {
485             if (DxS_data[i] == T0_OVER)
486             {
487                 lcxdT[i] = false;
488             }
489         }
490 
491         compute_gates();
492     }
493 }
494 
495 
496 // Handle T1 overflow notification
t1_overflow()497 void CLC_BASE::t1_overflow()
498 {
499     bool gate_change = false;
500 
501     for (int i = 0; i < 4; i++)
502     {
503         if (DxS_data[i] == T1_OVER)
504         {
505             lcxdT[i] = true;
506             gate_change = true;
507         }
508     }
509 
510     if (gate_change)
511     {
512         Dprintf(("CLC%u t1_overflow() enable=%d\n", index + 1,
513                  CLCenabled()));
514         compute_gates();
515 
516         for (int i = 0; i < 4; i++)
517         {
518             if (DxS_data[i] == T1_OVER)
519             {
520                 lcxdT[i] = false;
521             }
522         }
523 
524         compute_gates();
525     }
526 }
527 
528 
529 // Handle T[246] match notification
530 // If an input gate using a t[246]  match, toggle input gate
t2_match(char tmr_number)531 void CLC_BASE::t2_match(char tmr_number)
532 {
533     bool gate_change = false;
534 
535     for (int i = 0; i < 4; i++)
536     {
537         if (
538             (DxS_data[i] == T2_MATCH && tmr_number == '2') ||
539             (DxS_data[i] == T4_MATCH && tmr_number == '4') ||
540             (DxS_data[i] == T6_MATCH && tmr_number == '6')
541         )
542         {
543             lcxdT[i] = true;
544             gate_change = true;
545         }
546     }
547 
548     if (gate_change)
549     {
550         Dprintf(("CLC%u t2_match(%c) enable=%d\n", index + 1, tmr_number, CLCenabled()));
551         compute_gates();
552 
553         for (int i = 0; i < 4; i++)
554         {
555             if (
556                 (DxS_data[i] == T2_MATCH && tmr_number == '2') ||
557                 (DxS_data[i] == T4_MATCH && tmr_number == '4') ||
558                 (DxS_data[i] == T6_MATCH && tmr_number == '6')
559             )
560             {
561                 lcxdT[i] = false;
562             }
563         }
564 
565         compute_gates();
566     }
567 }
568 
569 
570 // Handle updates for frc or lfintosc
osc_out(bool level,int kind)571 void CLC_BASE::osc_out(bool level, int kind)
572 {
573     bool gate_change = false;
574 
575     for (int i = 0; i < 4; i++)
576     {
577         if (DxS_data[i] == kind && lcxdT[i] != level)
578         {
579             lcxdT[i] = level;
580             gate_change = true;
581         }
582     }
583 
584     if (gate_change)
585     {
586         Dprintf(("CLC%u osc_out() kind=%d level=%d enable=%d\n", index + 1,
587                  kind, level, CLCenabled()));
588         compute_gates();
589     }
590 }
591 
592 
593 // Handle updates for NCO module
NCO_out(bool level)594 void CLC_BASE::NCO_out(bool level)
595 {
596     if (NCO_level != level)
597     {
598         bool gate_change = false;
599         NCO_level = level;
600 
601         for (int i = 0; i < 4; i++)
602         {
603             if (DxS_data[i] == NCOx)
604             {
605                 lcxdT[i] = level;
606                 gate_change = true;
607             }
608         }
609 
610         if (gate_change)
611         {
612             Dprintf(("CLC%u NCO_out() level=%d enable=%d\n", index + 1,
613                      level, CLCenabled()));
614             compute_gates();
615         }
616     }
617 }
618 
619 // Handle updates for ZCD module
ZCDx_out(bool level)620 void CLC_BASE::ZCDx_out(bool level)
621 {
622     if (ZCD_level != level)
623     {
624         bool gate_change = false;
625         ZCD_level = level;
626 
627         for (int i = 0; i < 4; i++)
628         {
629             if (DxS_data[i] == ZCD_OUT)
630             {
631                 lcxdT[i] = level;
632                 gate_change = true;
633             }
634         }
635 
636         if (gate_change)
637         {
638             Dprintf(("CLC%u ZCD_out() level=%d enable=%d\n", index + 1,
639                      level, CLCenabled()));
640             compute_gates();
641         }
642     }
643 }
644 
645 
646 // Handle updates from comparator module
CxOUT_sync(bool level,int cm)647 void CLC_BASE::CxOUT_sync(bool level, int cm)
648 {
649     if (CMxOUT_level[cm] != level)
650     {
651         bool gate_change = false;
652         CMxOUT_level[cm] = level;
653 
654         for (int i = 0; i < 4; i++)
655         {
656             if ((DxS_data[i] == C1OUT && cm == 0) ||
657                     (DxS_data[i] == C2OUT && cm == 1))
658             {
659                 lcxdT[i] = level;
660                 gate_change = true;
661             }
662         }
663 
664         if (gate_change)
665         {
666             Dprintf(("CLC%u C%dOUT_sync() level=%d enable=%d\n", index + 1,
667                      cm + 1, level, CLCenabled()));
668             compute_gates();
669         }
670     }
671 }
672 
673 
674 // Handle updates from pwm module
out_pwm(bool level,int id)675 void CLC_BASE::out_pwm(bool level, int id)
676 {
677     Dprintf(("CLC%u out_pwm() pwm%d level=%d enable=%d\n", index + 1, id + 1,
678              level, CLCenabled()));
679 
680     if (pwmx_level[id] != level)
681     {
682         bool gate_change = false;
683         pwmx_level[id] = level;
684 
685         for (int i = 0; i < 4; i++)
686         {
687             if ((DxS_data[i] == PWM1 && id == 0) ||
688                     (DxS_data[i] == PWM2 && id == 1) ||
689                     (DxS_data[i] == PWM3 && id == 2) ||
690                     (DxS_data[i] == PWM4 && id == 3))
691             {
692                 lcxdT[i] = level;
693                 gate_change = true;
694             }
695         }
696 
697         if (gate_change)
698         {
699             Dprintf(("CLC%u out_pwm() pwm%d level=%d enable=%d\n",
700                      index + 1, id + 1, level, CLCenabled()));
701             compute_gates();
702         }
703     }
704 }
705 
706 
707 // notification on CLCxIN[12]
setState(char new3State,int id)708 void CLC_BASE::setState(char new3State, int id)
709 {
710     bool state = (new3State == '1' || new3State == 'W');
711 
712     if (state != INxstate[id])
713     {
714         bool gate_change = false;
715         INxstate[id] = state;
716 
717         for (int i = 0; i < 4; i++)
718         {
719             if ((DxS_data[i] == CLCxIN0 && id == 0) ||
720                     (DxS_data[i] == CLCxIN1 && id == 1))
721             {
722                 lcxdT[i] = state;
723                 gate_change = true;
724             }
725         }
726 
727         if (gate_change)
728         {
729             Dprintf(("CLC%u setState() IN%d level=%d enable=%d\n",
730                      index + 1, id, state, CLCenabled()));
731             compute_gates();
732         }
733     }
734 }
735 
736 
737 // Enable/Disable input pin i
enableINxpin(int i,bool on)738 void CLC_BASE::enableINxpin(int i, bool on)
739 {
740     if (on)
741     {
742         if (!INxactive[i])
743         {
744             char name[7] = "LCyINx";
745 
746             if (!INxgui[i].length())
747             {
748                 INxgui[i] = pinCLCxIN[i]->getPin().GUIname();
749             }
750 
751             name[2] = '0' + index;
752             name[5] = '0' + i;
753             pinCLCxIN[i]->getPin().newGUIname(name);
754 
755             if (!INxsink[i])
756             {
757                 INxsink[i] = new INxSignalSink(this, i);
758             }
759 
760             pinCLCxIN[i]->addSink(INxsink[i]);
761             setState(pinCLCxIN[i]->getPin().getState() ? '1' : '0', i);
762         }
763 
764         INxactive[i]++;
765 
766     }
767     else if (!--INxactive[i])
768     {
769         if (INxgui[i].length())
770         {
771             pinCLCxIN[i]->getPin().newGUIname(INxgui[i].c_str());
772 
773         }
774         else
775             pinCLCxIN[i]->getPin().newGUIname(pinCLCxIN[i]->getPin().
776                                               name().c_str());
777 
778         if (INxsink[i])
779         {
780             pinCLCxIN[i]->removeSink(INxsink[i]);
781         }
782     }
783 }
784 
785 
786 // Enable/disable output pin
oeCLCx(bool on)787 void CLC_BASE::oeCLCx(bool on)
788 {
789     if (on)
790     {
791         if (!srcCLCxactive)
792         {
793             char name[] = "CLCx";
794             name[3] = '1' + index;
795             CLCxgui = pinCLCx->getPin().GUIname();
796             pinCLCx->getPin().newGUIname(name);
797 
798             if (!CLCxsrc)
799             {
800                 CLCxsrc = new CLCSigSource(this, pinCLCx);
801             }
802 
803             pinCLCx->setSource(CLCxsrc);
804             srcCLCxactive = true;
805             CLCxsrc->setState((clcxcon.value.get() & LCxOE) ? '1' : '0');
806             pinCLCx->updatePinModule();
807         }
808 
809     }
810     else if (srcCLCxactive)
811     {
812         if (CLCxgui.length())
813         {
814             pinCLCx->getPin().newGUIname(CLCxgui.c_str());
815 
816         }
817         else
818             pinCLCx->getPin().newGUIname(pinCLCx->getPin().name().
819                                          c_str());
820 
821         pinCLCx->setSource(0);
822         delete CLCxsrc;
823         CLCxsrc = nullptr;
824         srcCLCxactive = false;
825         pinCLCx->updatePinModule();
826     }
827 }
828 
829 
830 // Update the output value of each of the 4 Data Gates
831 // taking into account both input and output polarity
compute_gates()832 void CLC_BASE::compute_gates()
833 {
834     unsigned int glsx[] =
835     {
836         clcxgls0.value.get(), clcxgls1.value.get(),
837         clcxgls2.value.get(), clcxgls3.value.get()
838     };
839     int mask;
840     unsigned int pol = clcxpol.value.get();
841 
842     for (int j = 0; j < 4; j++)
843     {
844         bool gate_out = false;
845         mask = 1;
846 
847         for (int i = 0; i < 4; i++)
848         {
849             if (glsx[j] & mask)
850             {
851                 gate_out = !lcxdT[i];
852             }
853 
854             mask <<= 1;
855 
856             if (glsx[j] & mask)
857             {
858                 gate_out = lcxdT[i];
859             }
860 
861             mask <<= 1;
862         }
863 
864         gate_out = (pol & (1 << j)) ? !gate_out : gate_out;
865         lcxg[j] = gate_out;
866     }
867 
868     if (CLCenabled())
869     {
870         Dprintf(("CLC_BASE::compute_gates CLC%u lcxdT = {%d %d %d %d} lcxg={%d %d %d %d}\n", index + 1, lcxdT[0], lcxdT[1], lcxdT[2], lcxdT[3], lcxg[0], lcxg[1], lcxg[2], lcxg[3]));
871     }
872 
873     cell_function();
874 }
875 
876 
877 // Select and execute cell functions
cell_function()878 void CLC_BASE::cell_function()
879 {
880     bool out = false;
881     unsigned int con = clcxcon.value.get();
882     unsigned int pol = clcxpol.value.get();
883 
884     switch (con & 0x7)
885     {
886     case 0:			// AND-OR
887         out = (lcxg[0] && lcxg[1]) || (lcxg[2] && lcxg[3]);
888         break;
889 
890     case 1:			// OR-XOR
891         out = (lcxg[0] || lcxg[1]) ^ (lcxg[2] || lcxg[3]);
892         break;
893 
894     case 2:			// 4 input AND
895         out = lcxg[0] && lcxg[1] && lcxg[2] && lcxg[3];
896         break;
897 
898     case 3:
899         out = cell_sr_latch();
900         break;
901 
902     case 4:
903         out = cell_1_in_flipflop();
904         break;
905 
906     case 5:
907         out = cell_2_in_flipflop();
908         break;
909 
910     case 6:
911         out = JKflipflop();
912         break;
913 
914     case 7:
915         out = transparent_D_latch();
916         break;
917     }
918 
919     if (pol & LCxPOL)
920     {
921         out = !out;
922     }
923 
924     if (CLCenabled())
925     {
926         outputCLC(out);
927     }
928 }
929 
930 
931 // Send output to required consumers
outputCLC(bool out)932 void CLC_BASE::outputCLC(bool out)
933 {
934     unsigned int con = clcxcon.value.get();
935     bool old_out = con & LCxOUT;
936     Dprintf(("outputCLC CLC%u out=%d old_out=%d clcdata=0x%x\n", index, out,
937              old_out, clcdata->value.get()));
938 
939     if (out)
940     {
941         con |= LCxOUT;
942 
943     }
944     else
945     {
946         con &= ~LCxOUT;
947     }
948 
949     clcxcon.value.put(con);
950     assert(m_Interrupt);
951     Dprintf(("CLC_BASE::outputCLC CLC%u old_out %d out %d int 0x%x \n", index + 1,
952              old_out, out, con & LCxINTP));
953 
954     if (!old_out && out && (con & LCxINTP))  	//Positive edge interrupt
955     {
956         m_Interrupt->Trigger();
957     }
958 
959     if (old_out && !out && (con & LCxINTN))  	//Negative edge interrupt
960     {
961         m_Interrupt->Trigger();
962     }
963 
964     assert(clcdata);
965     clcdata->set_bit(out, index);
966 
967     // send output to other modules
968     if (p_nco)
969         p_nco->link_nco(out, index);
970 
971     if (p_cog)
972         p_cog->out_clc(out, index);
973 
974     if (CLCenabled())
975     {
976         CLCxsrc->setState(out ? '1' : '0');
977         pinCLCx->updatePinModule();
978     }
979 }
980 
981 
cell_sr_latch()982 bool CLC_BASE::cell_sr_latch()
983 {
984     bool set = lcxg[0] || lcxg[1];
985     bool reset = lcxg[2] || lcxg[3];
986 
987     if (set)
988     {
989         Doutput = true;
990 
991     }
992     else if (reset)
993     {
994         Doutput = false;
995     }
996 
997     return Doutput;
998 }
999 
1000 
cell_1_in_flipflop()1001 bool CLC_BASE::cell_1_in_flipflop()
1002 {
1003     bool set = lcxg[3];
1004     bool reset = lcxg[2];
1005     bool clock = lcxg[0];
1006     bool D = lcxg[1];
1007 
1008     if (set)
1009     {
1010         Doutput = true;
1011 
1012     }
1013     else if (reset)
1014     {
1015         Doutput = false;
1016 
1017     }
1018     else if (!Dclock && clock)
1019     {
1020         Doutput = D;
1021     }
1022 
1023     Dclock = clock;
1024     return Doutput;
1025 }
1026 
1027 
cell_2_in_flipflop()1028 bool CLC_BASE::cell_2_in_flipflop()
1029 {
1030     bool reset = lcxg[2];
1031     bool clock = lcxg[0];
1032     bool D = lcxg[1] || lcxg[3];
1033 
1034     if (reset)
1035     {
1036         Doutput = false;
1037 
1038     }
1039     else if (!Dclock && clock)
1040     {
1041         Doutput = D;
1042     }
1043 
1044     Dclock = clock;
1045     return Doutput;
1046 }
1047 
1048 
JKflipflop()1049 bool CLC_BASE::JKflipflop()
1050 {
1051     bool J = lcxg[1];
1052     bool K = lcxg[3];
1053     bool reset = lcxg[2];
1054     bool clock = lcxg[0];
1055 
1056     if (reset)
1057     {
1058         Doutput = false;
1059 
1060     }
1061     else if (!Dclock && clock)  	// Clock + edge
1062     {
1063         if (J && K)  	// Toggle output
1064         {
1065             Doutput = !Doutput;
1066 
1067         }
1068         else if (J && !K)  	// Set output
1069         {
1070             Doutput = true;
1071 
1072         }
1073         else if (!J && K)  	// clear output
1074         {
1075             Doutput = false;
1076 
1077         }
1078         else if (!J && !K)    // no change
1079         {
1080             ;
1081         }
1082     }
1083 
1084     Dclock = clock;
1085     return Doutput;
1086 }
1087 
1088 
transparent_D_latch()1089 bool CLC_BASE::transparent_D_latch()
1090 {
1091     bool reset = lcxg[0];
1092     bool D = lcxg[1];
1093     bool LE = lcxg[2];
1094     bool set = lcxg[3];
1095 
1096     if (set)
1097     {
1098         Doutput = true;
1099 
1100     }
1101     else if (reset)
1102     {
1103         Doutput = false;
1104 
1105     }
1106     else if (!LE)
1107     {
1108         Doutput = D;
1109     }
1110 
1111     return Doutput;
1112 }
1113 
1114 
releasePinSource(PinModule * pin)1115 void CLC_BASE::releasePinSource(PinModule * pin)
1116 {
1117     if (pin == pinCLCx)
1118     {
1119         srcCLCxactive = false;
1120     }
1121 }
1122 
1123 
1124 // Called from clcdata, process LCx_OUT updates where x = pos
lcxupdate(bool bit_val,unsigned int pos)1125 void CLC_BASE::lcxupdate(bool bit_val, unsigned int pos)
1126 {
1127     bool update = false;
1128 
1129     for (int i = 0; i < 4; i++)
1130     {
1131         if ((lcxdT[i] != bit_val) &&
1132                 ((DxS_data[i] == LC1 && pos == 0) ||
1133                  (DxS_data[i] == LC2 && pos == 1) ||
1134                  (DxS_data[i] == LC3 && pos == 2) ||
1135                  (DxS_data[i] == LC4 && pos == 3)))
1136         {
1137             update = true;
1138             lcxdT[i] = bit_val;
1139         }
1140     }
1141 
1142     if (update)
1143     {
1144         if (CLCenabled())
1145             Dprintf(("CLC%u lcxupdate LC%u_OUT=%d\n", index + 1, pos + 1,
1146                      bit_val));
1147 
1148         compute_gates();
1149     }
1150 }
1151 
1152 
1153 // CLCCON register has changed
update_clccon(unsigned int diff)1154 void CLC_BASE::update_clccon(unsigned int diff)
1155 {
1156     unsigned int val = clcxcon.value.get();
1157 
1158     if (diff & LCxOE)
1159     {
1160         if ((val & (LCxOE | LCxEN)) == (LCxOE | LCxEN))
1161         {
1162             oeCLCx(true);
1163         }
1164 
1165         if ((val & (LCxOE | LCxEN)) == (LCxEN))
1166         {
1167             oeCLCx(false);
1168         }
1169     }
1170 
1171     if (diff & LCxEN)  	// clc off or on
1172     {
1173         if (val & LCxEN)  	// CLC on
1174         {
1175             config_inputs(true);
1176 
1177         }
1178         else  		// CLC off
1179         {
1180             config_inputs(false);
1181             oeCLCx(false);
1182         }
1183     }
1184 }
1185 
1186 
1187 // Initialize inputs as required, called when CLC is enabled or disabled
1188 // or changes in clcxselx clcxglsx while clc enabled
config_inputs(bool on)1189 void CLC_BASE::config_inputs(bool on)
1190 {
1191     unsigned int active_gates = clcxgls0.value.get() |
1192                                 clcxgls1.value.get() | clcxgls2.value.get() | clcxgls3.value.get();
1193     Dprintf(("config_inputs CLC%u on=%d active_gates=0x%x\n", index + 1, on,
1194              active_gates));
1195     bool haveIN[4] = {false, false, false, false};
1196     bool haveFRC = false;
1197     bool haveLFINTOSC = false;
1198     bool haveHFINTOSC = false;
1199     int mask = 3;
1200 
1201     for (int i = 0; i < 4; i++)
1202     {
1203         if (active_gates & mask)  	// data input used
1204         {
1205             if (DxS_data[i] == CLCxIN0) { haveIN[0] = true; }
1206             else if (DxS_data[i] == CLCxIN1) { haveIN[1] = true; }
1207             else if (DxS_data[i] == CLCxIN2) { haveIN[2] = true; }
1208             else if (DxS_data[i] == CLCxIN3) { haveIN[3] = true; }
1209             else if (DxS_data[i] == FRC_IN) { haveFRC = true; }
1210             else if (DxS_data[i] == LFINTOSC) { haveLFINTOSC = true; }
1211             else if (DxS_data[i] == HFINTOSC) { haveHFINTOSC = true; }
1212         }
1213 
1214         mask <<= 2;
1215     }
1216 
1217     // If on==true and inactive, turn on
1218     // if on==false and active. turn off
1219 
1220 
1221     for (int i = 0; i<4; i++)
1222     {
1223         if (haveIN[i] && (INxactive[i] ^ on))
1224         {
1225             Dprintf(("config_inputs CLC%u IN%d on=%d\n", index + 1, i, on));
1226             enableINxpin(i, on);
1227 
1228         }
1229         else if (!haveIN[i] && INxactive[i])
1230         {
1231             Dprintf(("config_inputs CLC%u IN%d OFF on=%d\n", index + 1, i, on));
1232             enableINxpin(i, false);
1233         }
1234     }
1235 
1236 
1237     if (haveFRC && (FRCactive ^ on))
1238     {
1239         Dprintf(("config_inputs CLC%u FRC FRCactive=%d on=%d\n", index + 1,
1240                  FRCactive, on));
1241         FRCactive = on;
1242         frc->start_osc_sim(on);
1243 
1244     }
1245     else if (!haveFRC && FRCactive)
1246     {
1247         Dprintf(("config_inputs CLC%u FRC OFF  on=%d\n", index + 1, on));
1248         FRCactive = false;
1249         frc->start_osc_sim(false);
1250     }
1251 
1252     if (haveLFINTOSC && (LFINTOSCactive ^ on))
1253     {
1254         Dprintf(("config_inputs CLC%u LFINTOSC LFINTOSCactive=%d on=%d\n",
1255                  index + 1, LFINTOSCactive, on));
1256         LFINTOSCactive = on;
1257         lfintosc->start_osc_sim(on);
1258 
1259     }
1260     else if (!haveLFINTOSC && LFINTOSCactive)
1261     {
1262         Dprintf(("config_inputs CLC%u LFINTOSC OFF  on=%d\n", index + 1,
1263                  on));
1264         LFINTOSCactive = false;
1265         lfintosc->start_osc_sim(false);
1266     }
1267 
1268     if (haveHFINTOSC && (HFINTOSCactive ^ on))
1269     {
1270         Dprintf(("config_inputs CLC%u HFINTOSC HFINTOSCactive=%d on=%d\n",
1271                  index + 1, HFINTOSCactive, on));
1272         HFINTOSCactive = on;
1273         hfintosc->start_osc_sim(on);
1274 
1275     }
1276     else if (!haveHFINTOSC && HFINTOSCactive)
1277     {
1278         Dprintf(("config_inputs CLC%u HFINTOSC OFF  on=%d\n", index + 1,
1279                  on));
1280         HFINTOSCactive = false;
1281         hfintosc->start_osc_sim(false);
1282     }
1283 
1284     if (on)
1285     {
1286         compute_gates();
1287     }
1288 }
1289 
1290 
CLC_4SEL(Processor * cpu,unsigned int _index,CLCDATA * _clcdata)1291 CLC_4SEL::CLC_4SEL(Processor * cpu, unsigned int _index, CLCDATA * _clcdata)
1292     : CLC_BASE(cpu, _index, _clcdata),
1293       clcxsel0(this, cpu, "clcxsel0", "Multiplexer Data 1 Select Register", 0),
1294       clcxsel1(this, cpu, "clcxsel1", "Multiplexer Data 2 Select Register", 1),
1295       clcxsel2(this, cpu, "clcxsel2", "Multiplexer Data 3 Select Register", 2),
1296       clcxsel3(this, cpu, "clcxsel3", "Multiplexer Data 4 Select Register", 3)
1297 {
1298 }
1299 
1300 
1301 
1302 
1303 // OSC_SIM simulates clock inputs for CLC.
1304 // If the requested frequency > FOSC/4, OSC_SIM will generate pulses at
1305 // a frequency of FOSC/4.
1306 // If the requested frequency is not a whole fraction of FOSC/4, the
1307 // simulated clock will have jitter to approximate the requested frequency.
1308 // The duty cycle of the simulated frequency will only be 50% when
1309 // the requested frequency is a whole fraction of FOSC/8.
OSC_SIM(double _freq,int _data_in)1310 OSC_SIM::OSC_SIM(double _freq, int _data_in)
1311     : frequency(_freq), data_in(_data_in)
1312 {
1313     for (int i = 0; i < 4; i++)
1314     {
1315         m_clc[i] = nullptr;
1316     }
1317 }
1318 
1319 
start_osc_sim(bool on)1320 void OSC_SIM::start_osc_sim(bool on)
1321 {
1322     if (on)
1323     {
1324         Dprintf(("OSC_SIM::start_osc_sim freq=%.0f kHz active %d\n",
1325                  frequency / 1000.0, active));
1326 
1327         if (!active)
1328         {
1329             int cycles = get_cycles().instruction_cps() / frequency + 0.5;
1330 
1331             if (cycles < 2)
1332             {
1333                 fprintf(stderr,
1334                         "OSC_SIM  %.1f kHz not simulated at current CPU frequency\n",
1335                         frequency / 1000.0);
1336                 fprintf(stderr, "Using pulses at %.1f kHz\n",
1337                         get_cycles().instruction_cps() / 1000.0);
1338                 cycles = 1;
1339             }
1340 
1341             adjust_cycles =
1342                 frequency - get_cycles().instruction_cps() / cycles;
1343             next_cycle = cycles / 2;
1344             level = true;
1345 
1346             for (int i = 0; i < 4; i++)
1347             {
1348                 if (m_clc[i])
1349                 {
1350                     m_clc[i]->osc_out(level, data_in);
1351                 }
1352             }
1353 
1354             if (future_cycle)
1355             {
1356                 get_cycles().clear_break(this);
1357             }
1358 
1359             future_cycle = get_cycles().get() + cycles - next_cycle;
1360             get_cycles().set_break(future_cycle, this);
1361             Dprintf(("OSC_SIM::start_osc_sim cycles=%d adj_cycles=%" PRINTF_GINT64_MODIFIER "d freq=%.1f kHz inst_cps=%e\n", cycles, adjust_cycles, frequency / 1000.0, get_cycles().instruction_cps()));
1362         }
1363 
1364         active++;
1365 
1366     }
1367     else if (--active == 0)
1368     {
1369         Dprintf(("OSC_SIM::start_osc_sim stop freq=%.0f\n",
1370                  frequency / 1000.0));
1371 
1372         if (future_cycle)
1373         {
1374             get_cycles().clear_break(this);
1375             future_cycle = 0;
1376         }
1377     }
1378 }
1379 
1380 
callback()1381 void OSC_SIM::callback()
1382 {
1383     for (int i = 0; i < 4; i++)
1384     {
1385         if (m_clc[i])
1386         {
1387             m_clc[i]->osc_out(!level, data_in);
1388         }
1389     }
1390 
1391     if (!next_cycle && level)  	// Sending a pulse
1392     {
1393         for (int i = 0; i < 4; i++)
1394         {
1395             if (m_clc[i])
1396             {
1397                 m_clc[i]->osc_out(level, data_in);
1398             }
1399         }
1400     }
1401 
1402     if (next_cycle)
1403     {
1404         future_cycle = get_cycles().get() + next_cycle;
1405         next_cycle = 0;
1406         level = false;
1407 
1408     }
1409     else
1410     {
1411         adjust_cycles += frequency;
1412         int cycles = get_cycles().instruction_cps() / adjust_cycles + 0.5;
1413 
1414         if (cycles < 2)
1415         {
1416             cycles = 1;
1417             adjust_cycles = 0;
1418 
1419         }
1420         else
1421         {
1422             adjust_cycles -= get_cycles().instruction_cps() / cycles;
1423         }
1424 
1425         next_cycle = cycles / 2;
1426         level = true;
1427         future_cycle = get_cycles().get() + cycles - next_cycle;
1428     }
1429 
1430     get_cycles().set_break(future_cycle, this);
1431 }
1432