summaryrefslogtreecommitdiffstats
path: root/src/simulator.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/simulator.h')
-rw-r--r--src/simulator.h247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/simulator.h b/src/simulator.h
new file mode 100644
index 0000000..a6ade3a
--- /dev/null
+++ b/src/simulator.h
@@ -0,0 +1,247 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef SIMULATOR_H
+#define SIMULATOR_H
+
+#include "circuit.h"
+#include "logic.h"
+
+/**
+This should be a multiple of 1000. It is the number of times a second that
+linear elements are updated.
+*/
+const int LINEAR_UPDATE_RATE = int(1e4);
+
+/**
+This should be a multiple of 1000. It is the number of times a second that
+logic elements are updated.
+*/
+const int LOGIC_UPDATE_RATE = int(1e6);
+
+
+class Circuit;
+class CircuitDocument;
+class Component;
+class ComponentCallback;
+class ECNode;
+class GpsimProcessor;
+class LogicIn;
+class LogicOut;
+class Switch;
+class Wire;
+
+typedef QValueList<ECNode*> ECNodeList;
+typedef QValueList<LogicIn*> LogicInList;
+
+typedef void(Component::*VoidCallbackPtr)();
+
+template <typename T>
+class LinkedList
+{
+ public:
+ LinkedList( T * data ) { m_pData = data; m_pNext = 0l; }
+ T * data() const { return m_pData; }
+
+ LinkedList<T> * m_pNext;
+
+ protected:
+ T * m_pData;
+};
+
+
+class ComponentCallback
+{
+ public:
+ ComponentCallback( Component * component, VoidCallbackPtr function )
+ {
+ m_pComponent = component;
+ m_pFunction = function;
+ }
+
+ void callback() { (m_pComponent->*m_pFunction)(); }
+ Component * component() const { return m_pComponent; }
+
+ protected:
+ Component * m_pComponent;
+ VoidCallbackPtr m_pFunction;
+};
+
+
+/**
+This singleton class oversees all simulation (keeping in sync linear, nonlinear,
+logic, external simulators (such as gpsim), mechanical simulation, etc).
+@author David Saxton
+*/
+class Simulator : public QObject
+{
+ Q_OBJECT
+ public:
+ static Simulator * self();
+ ~Simulator();
+
+ /**
+ * Number of (1/LOGIC_UPDATE_RATE) intervals that the simulator has been
+ * stepping for.
+ */
+ long long time() const { return m_stepNumber*(long long)(LOGIC_UPDATE_RATE/LINEAR_UPDATE_RATE) + m_llNumber; }
+ /**
+ * Initializes a new logic chain.
+ */
+ void createLogicChain( LogicOut * logicOut, const LogicInList & logicInList, const PinList & pinList );
+ /**
+ * Adds the given LogicOut to the list of changed LogicOuts
+ */
+ void addChangedLogic( LogicOut * changed )
+ {
+ m_pChangedLogicLast->setNextChanged( changed, m_currentChain );
+ m_pChangedLogicLast = changed;
+ }
+ /**
+ * Remove pointers to the given LogicOut, called when it is deleted for
+ * safety reasons.
+ */
+ void removeLogicOutReferences( LogicOut * logic );
+ /**
+ * Remove pointers to the given LogicIn, called when it is deleted for
+ * safety reasons. Simulator does not have any references to LogicIns
+ * itself - instead, they are removed from logic chains which are
+ * currently marked as changed.
+ */
+ void removeLogicInReferences( LogicIn * logic );
+ /**
+ * Adds the given Circuit to the list of changed Circuits
+ */
+ void addChangedCircuit( Circuit * changed )
+ {
+ m_pChangedCircuitLast->setNextChanged( changed, m_currentChain );
+ m_pChangedCircuitLast = changed;
+ }
+ inline void addStepCallback( int at, LinkedList<ComponentCallback> * ccb );
+ /**
+ * Add the given processor to the simulator. GpsimProcessor::step will
+ * be called while present in the simulator (it is at GpsimProcessor's
+ * disgression whether to actually step, depending on its running
+ * status).
+ * @see detachGpsimProcessor( GpsimProcessor * cpu );
+ */
+ void attachGpsimProcessor( GpsimProcessor * cpu );
+ /**
+ * Remove the given processor from the simulation loop
+ */
+ void detachGpsimProcessor( GpsimProcessor * cpu );
+ /**
+ * Attach the component callback to the simulator. This will be called
+ * during the logic update loop, at LOGIC_UPDATE_RATE times per second (so
+ * make sure the function passed is an efficient one!).
+ */
+ void attachComponentCallback( Component * component, VoidCallbackPtr function );
+ /**
+ * Removes the callbacks for the given component from the simulator.
+ */
+ void detachComponentCallbacks( Component * component );
+ /**
+ * Attach the component to the simulator.
+ */
+ void attachComponent( Component * component );
+ /**
+ * Detaches the component from the simulator.
+ */
+ void detachComponent( Component * component );
+ /**
+ * Attach a circuit to the simulator
+ */
+ void attachCircuit( Circuit * circuit );
+ /**
+ * Detach a circuit from the simulator.
+ */
+ void detachCircuit( Circuit * circuit );
+ /**
+ * Attaches the switch to the simulator (only needed when the switch has
+ * started bouncing.
+ */
+ void attachSwitch( Switch * sw );
+ /**
+ * Detaches the switch from the simulator (called when the switch has
+ * stopped bouncing).
+ */
+ void detachSwitch( Switch * sw );
+ /**
+ * @return whether or not we are currently simulating stuff
+ * @see slotSetSimulating
+ */
+ bool isSimulating() const { return m_bIsSimulating; }
+
+ public slots:
+ /**
+ * Set whether or not to simulate at the moment.
+ * @see isSimulating
+ */
+ void slotSetSimulating( bool simulate );
+
+ signals:
+ /**
+ * Emitted when the simulating state changes.
+ * @see slotSetSimulating
+ */
+ void simulatingStateChanged( bool isSimulating );
+
+ private slots:
+ void step();
+
+ protected:
+ template <typename T>
+ void attach( LinkedList<T> ** start, T * data );
+ template <typename T>
+ void detach( LinkedList<T> ** start, T * data );
+ template <typename T>
+ void detachAll( LinkedList<T> * list );
+
+ bool m_bIsSimulating;
+ static Simulator * m_pSelf;
+
+ ///List of LogicOuts that are at the start of a LogicChain
+ QValueList<LogicOut*> m_logicChainStarts;
+
+ LogicOut * m_pChangedLogicStart;
+ LogicOut * m_pChangedLogicLast;
+
+ Circuit * m_pChangedCircuitStart;
+ Circuit * m_pChangedCircuitLast;
+
+ LinkedList<GpsimProcessor> * m_gpsimProcessors;
+ LinkedList<Component> * m_components;
+ LinkedList<ComponentCallback> * m_componentCallbacks;
+ LinkedList<Circuit> * m_ordinaryCircuits;
+ LinkedList<Switch> * m_switches;
+
+ LinkedList<ComponentCallback> * m_pStartStepCallback[LOGIC_UPDATE_RATE/LINEAR_UPDATE_RATE];
+ LinkedList<ComponentCallback> * m_pNextStepCallback[LOGIC_UPDATE_RATE/LINEAR_UPDATE_RATE];
+
+ private:
+ Simulator();
+ long m_llNumber;
+ long long m_stepNumber;
+ unsigned char m_currentChain;
+};
+
+
+inline void Simulator::addStepCallback( int at, LinkedList<ComponentCallback> * ccb )
+{
+ if ( !m_pStartStepCallback[at] )
+ m_pStartStepCallback[at] = ccb;
+
+ else
+ m_pNextStepCallback[at]->m_pNext = ccb;
+
+ m_pNextStepCallback[at] = ccb;
+}
+
+#endif