pin-pacer glue component

Robert Shideleff <[email protected]>
Newsgroups gmane.comp.emulators.sid.devel
Message-ID <[email protected]>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This patch adds a pin-pacer to the glue components.  I have used this 
successfully in combination with a socket component and netcat to feed test 
data from a file into the simulation at a simulation-realistic rate.

Bob
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFBESh68XjOGQDr37YRAhhpAJ4z7M4la5x3tVB8aAZ8BzJXS5yeDACaA0Bg
bm2FRa4shzEGS3MvXGMWs48=
=GlAT
-----END PGP SIGNATURE-----
sid-glue.diff (text/x-diff, 10.3 KB)
diff --exclude CVS --exclude='*.deps' --exclude='*.libs' --exclude=Makefile --exclude='*.lo' --exclude='*.la' --exclude='*.o' -u --new-file ../../../sid.orig/src/sid/component/glue/glue.cxx glue/glue.cxx
--- ../../../sid.orig/src/sid/component/glue/glue.cxx	2002-11-22 12:15:42.000000000 -0500
+++ glue/glue.cxx	2004-08-04 13:42:41.214170222 -0400
@@ -1,6 +1,7 @@
 // glue.cxx - miscellaneous glue components.  -*- C++ -*-
 
 // Copyright (C) 1999-2001 Red Hat.
+// Portions Copyright (C) 2004 Sirius Satellite Radio Inc.
 // This file is part of SID and is licensed under the GPL.
 // See the file COPYING.SID for conditions for redistribution.
 
@@ -557,11 +558,184 @@
 
 // ----------------------------------------------------------------------------
 
+  // The pin pacer component paces pin signals based on a trigger input 
+  class pin_pacer_component: public virtual component,
+			    protected fixed_pin_map_component,
+			    protected no_accessor_component,
+			    protected fixed_attribute_map_component,
+			    protected no_relation_component,
+			    protected no_bus_component,
+			    protected recursion_limited
+  {
+    host_int_4 trace;
+    host_int_4 signals_per_tick;
+    callback_pin<pin_pacer_component> tick;
+    callback_pin<pin_pacer_component> input;
+    output_pin request_input;
+    output_pin output;
+
+    deque<host_int_4> data_fifo;
+
+    friend class self_watcher<pin_pacer_component>;
+    self_watcher<pin_pacer_component> triggerpoint_manager;
+
+    void handle_input(host_int_4 value)
+      {
+        data_fifo.push_back(value);
+	triggerpoint_manager.check_and_dispatch();
+      }
+
+    void handle_tick(host_int_4 value)
+      {
+      	unsigned long output_count = data_fifo.size();
+
+	while(output_count < signals_per_tick)
+	{ 
+	  if(trace)
+	    printf("Requesting Data.\n");
+
+	  request_input.drive(0);
+
+	  // Give up if our souce isn't giving us any data.
+	  if(data_fifo.size() == output_count)
+	    break;
+
+	  output_count = data_fifo.size();
+	}
+
+	if(output_count > signals_per_tick)
+	  output_count = signals_per_tick;
+	
+	if(trace)
+	{
+	  printf("Tick:");
+	  if(output_count != signals_per_tick)
+	    printf(" Underflow:");
+	  printf(" Outputting:");
+	}
+        while(output_count-- > 0)
+	{
+	  if(trace)
+	    printf(" %X", data_fifo[0]);
+	  output.drive(data_fifo[0]);
+	  data_fifo.pop_front();
+	}
+	if(trace)
+	  printf(".\n");
+
+	triggerpoint_manager.check_and_dispatch();
+      }
+
+    friend ostream& operator << (ostream& o, const pin_pacer_component& it);
+    friend istream& operator >> (istream& i, pin_pacer_component& it);
+    string save_state() { return make_attribute(*this); }
+    component::status restore_state(const string& state) { return parse_attribute(state, *this); }
+
+    // Virtual pin interfaces between self_watcher and fixed_pin_map_component
+    sid::component::status 
+    pin_factory(const string& name)
+      {
+	return triggerpoint_manager.create_virtual_pin (name);
+      }
+
+    void
+    pin_junkyard(const string& name)
+      {
+	triggerpoint_manager.destroy_virtual_pin (name);
+      }
+
+
+  public:
+    pin_pacer_component ();
+    ~pin_pacer_component () throw() { };
+  };
+
+
+pin_pacer_component::pin_pacer_component():
+  recursion_limited ("pin signal sequencing"), 
+  signals_per_tick (1), 
+  trace (0), 
+  input (this, &pin_pacer_component::handle_input),
+  tick (this, &pin_pacer_component::handle_tick),
+  triggerpoint_manager (this)
+{
+  add_attribute ("trace?", &trace, "setting");
+  triggerpoint_manager.add_watchable_attribute ("trace?");
+  
+  add_attribute ("signals-per-tick", & signals_per_tick, "setting");
+  triggerpoint_manager.add_watchable_attribute ("signals-per-tick");
+  
+  add_pin ("input", & input);
+  add_attribute ("input", & input, "pin");
+  triggerpoint_manager.add_watchable_attribute ("input");
+  categorize ("input", "watchable");
+  
+  add_pin ("tick", & tick);
+  add_attribute ("tick", & tick, "pin");
+  triggerpoint_manager.add_watchable_attribute ("tick");
+  categorize ("tick", "watchable");
+  
+  add_pin ("request-input", & request_input);
+  add_attribute ("request-input", & request_input, "pin");
+  triggerpoint_manager.add_watchable_attribute ("request-input");
+  categorize ("request-input", "watchable");
+  
+  add_pin ("output", & output);
+  add_attribute ("output", & output, "pin");
+  triggerpoint_manager.add_watchable_attribute ("output");
+  categorize ("output", "watchable");
+  
+  add_attribute_virtual ("state-snapshot", this,
+			       & pin_pacer_component::save_state,
+			       & pin_pacer_component::restore_state);
+}
+  
+  
+  ostream& 
+  operator << (ostream& o, const pin_pacer_component& it)
+{
+  o << "pin_pacer ";
+  o << it.signals_per_tick << " ";
+  o << it.input << " ";
+  o << it.output << " ";
+  o << it.tick << " ";
+  o << it.request_input;
+  // NB: no whitespace at end!
+  return o;
+}
+
+  
+  istream&
+  operator >> (istream& i, pin_pacer_component& it)
+{
+  string key;
+  i >> key;
+  if (key != "pin_pacer")
+    {
+      i.setstate (ios::badbit);
+      return i;
+    }
+
+  i >> it.signals_per_tick;
+  
+  i >> it.input;
+  i >> it.output;
+  i >> it.tick;
+  i >> it.request_input;
+
+  return i;
+}
+
+
+
+// ----------------------------------------------------------------------------
+
   static
   vector<string>
   list_types()
 {
   vector<string> types;
+  types.push_back("hw-glue-pin-pacer");
   types.push_back("hw-glue-sequence");
   types.push_back("hw-glue-sequence-1");
   types.push_back("hw-glue-sequence-2");
@@ -577,6 +751,8 @@
   component*
   create(const string& typeName)
 {
+  if (typeName == "hw-glue-pin-pacer")
+    return new pin_pacer_component ();
   if (typeName == "hw-glue-sequence")
     return new sequence_component ();
   if (typeName == "hw-glue-sequence-1")
@@ -609,6 +785,8 @@
   if (g3) { delete g3; return; }
   bus_mux* g4 = dynamic_cast<bus_mux*>(c);
   if (g4) { delete g4; return; }
+  pin_pacer_component* g5 = dynamic_cast<pin_pacer_component*>(c);
+  if (g5) { delete g5; return; }
 }
 
   
diff --exclude CVS --exclude='*.deps' --exclude='*.libs' --exclude=Makefile --exclude='*.lo' --exclude='*.la' --exclude='*.o' -u --new-file ../../../sid.orig/src/sid/component/glue/hw-glue-pin-pacer.xml glue/hw-glue-pin-pacer.xml
--- ../../../sid.orig/src/sid/component/glue/hw-glue-pin-pacer.xml	1969-12-31 19:00:00.000000000 -0500
+++ glue/hw-glue-pin-pacer.xml	2004-08-04 14:18:09.258954102 -0400
@@ -0,0 +1,82 @@
+<?xml version="1.0" ?>
+<!DOCTYPE defcomplib SYSTEM "http://sources.redhat.com/sid/component.dtd">
+
+<defcomplib lib="libglue.la" dlsym="glue_component_library">
+  <defcomponent name="hw-glue-sequence" type="abstract">
+
+    <!-- pins -->
+    <defpin name="tick" direction="in" legalvalues="any" behaviors="data forwarding" />
+    <defpin name="request_input" direction="out" legalvalues="any" behaviors="data forwarding" />
+    <defpin name="input" direction="in" legalvalues="any" behaviors="data forwarding" />
+    <defpin name="output" direction="out" legalvalues="any" behaviors="data forwarding" />
+
+    <!-- attributes -->
+    <defattribute name="state-snapshot" category="no category" legalvalues="opaque string" behaviors="state save/restore" />
+    <defattribute name="signals-per-tick" category="setting, watchable" legalvalues="32 bit positive number" defaultvalue="1" behaviors="configuration" />
+    <defattribute name="tick" category="pin, watchable" behaviors="data forwarding" />
+    <defattribute name="request-input" category="pin, watchable" behaviors="data forwarding" />
+    <defattribute name="input" category="pin, watchable" behaviors="data forwarding" />
+    <defattribute name="output" category="pin, watchable" behaviors="data forwarding" />
+  </defcomponent>
+  <synop>
+    <p>
+      This component forwards signals received at its input to its output at a specified number of signals per tick.
+      This is useful for simulating baud rates in serial devices.
+    </p>
+  </synop>
+  <func>
+    <modelling>
+      <p>
+	 This component is a fifo for pin signals.
+      </p>
+    </modelling>
+    <behavior name="configuration">
+      <p>
+        <attribute>signals-per-tick</attribute> designates how many signal will be driven (if available) per incoming signal
+	on the tick pin.
+      </p>
+    </behavior>
+    <behavior name="data forwarding">
+      <p>
+	 This component is a fifo for pin signals. It will generate a duplicate pin signal on its output for every pin
+	 signal on its input at the pace configured in the attribute <attribute>signals-per-tick</attribute>. These
+	 signals will be generated whenever the tick input pin is driven. If the fifo contains less than signals-per-tick
+	 signals when tick is driven, then request-input will be driven. If no further signals arrive when request-input
+	 is driven, then output will be driven with whatever signals are available in the fifo. (If none are available,
+	 then none will be driven.) The fifo size is limited only by memory on the simulating pc. Note that input rate is
+	 not controlled. The device generating data (for example a stdio component or a socket component) can put data
+	 into the fifo at whatver rate it desires, which will simply require more memory to store the data until it
+	 can be driven out at the next tick. It is recommended that <pin>request-input</pin> be connected to the polling
+	 pin on whatever device is connected to <pin>input</pin>. On the stdio component for example, this would replace
+	 the input from a host scheduler.
+    </behavior>
+    <convention name="functional" supported="true">
+      <p>
+	This is a functional component.</p>
+    </convention>
+    <convention name="state save/restore" supported="true">
+      <p>
+	This component supports state save/restore 
+     </p>
+    </convention>
+    <convention name="triggerpoints" supported="true">
+      <p>
+	This component supports triggerpoints.
+      </p>
+    </convention>
+    <convention name="Recursion Control" supported="true">
+      <p>
+	This component limits recursion on the <pin>input</pin> pin.</p>
+    </convention>
+    <convention name="presentation" supported="true">
+      <p>
+	This component presents attributes in the <name>pin</name>, <name>setting</name>, and <name>watchable</name> categories.</p>
+    </convention>
+  </func>
+  <env>
+      <p>
+        This device is useful for modeling a baud rate on a serial device.
+     </p>
+  </env>
+</defcomplib>
+
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.