* sim/ucsim/*.*, sim/ucsim/configure, sim/ucsim/configure.in:
[fw/sdcc] / sim / ucsim / sim.src / hw.cc
index ed7f8162304c457e9ce53091a5c03f3414fbbddb..143e9b94b2de76020df5b50d174727aa7f55bf1a 100644 (file)
@@ -34,8 +34,85 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "hwcl.h"
 
 
-cl_hw::cl_hw(class cl_uc *auc, enum hw_cath cath, int aid, char *aid_string):
-  cl_base()
+/*
+ *____________________________________________________________________________
+ */
+
+cl_watched_cell::cl_watched_cell(class cl_address_space *amem, t_addr aaddr,
+                                 class cl_memory_cell **astore,
+                                 enum what_to_do_on_cell_change awtd)
+{
+  mem= amem;
+  addr= aaddr;
+  store= astore;
+  wtd= awtd;
+  if (mem)
+    {
+      cell= mem->get_cell(addr);
+      if (store)
+        *store= cell;
+    }
+}
+
+void
+cl_watched_cell::mem_cell_changed(class cl_address_space *amem, t_addr aaddr,
+                                  class cl_hw *hw)
+{
+  if (mem &&
+      mem == amem &&
+      addr == aaddr)
+    {
+      cell= mem->get_cell(addr);
+      if (store &&
+          (wtd & WTD_RESTORE))
+        *store= cell;
+      if (wtd & WTD_WRITE)
+        {
+          t_mem d= cell->get();
+          hw->write(cell, &d);
+        }
+    }
+}
+
+void
+cl_watched_cell::address_space_added(class cl_address_space *amem,
+                                     class cl_hw *hw)
+{
+}
+
+void
+cl_used_cell::mem_cell_changed(class cl_address_space *amem, t_addr aaddr, 
+class cl_hw *hw)
+{
+  if (mem &&
+      mem == amem &&
+      addr == aaddr)
+    {
+      cell= mem->get_cell(addr);
+      if (store &&
+          (wtd & WTD_RESTORE))
+        *store= cell;
+      if (wtd & WTD_WRITE)
+        {
+          t_mem d= cell->get();
+          hw->write(cell, &d);
+        }
+    }
+}
+
+void
+cl_used_cell::address_space_added(class cl_address_space *amem,
+                                  class cl_hw *hw)
+{
+}
+
+
+/*
+ *____________________________________________________________________________
+ */
+
+cl_hw::cl_hw(class cl_uc *auc, enum hw_cath cath, int aid, const char *aid_string):
+  cl_guiobj()
 {
   flags= HWF_INSIDE;
   uc= auc;
@@ -46,11 +123,50 @@ cl_hw::cl_hw(class cl_uc *auc, enum hw_cath cath, int aid, char *aid_string):
     id_string= strdup(aid_string);
   else
     id_string= strdup("unknown hw element");
+  char *s= (char*)malloc(strlen(get_name("hw"))+100);
+  sprintf(s, "partners of %s", get_name("hw"));
+  partners= new cl_list(2, 2, s);
+  sprintf(s, "watched cells of %s", get_name("hw"));
+  watched_cells= new cl_list(2, 2, s);
+  free(s);
 }
 
 cl_hw::~cl_hw(void)
 {
   free(id_string);
+  //hws_to_inform->disconn_all();
+  delete partners;
+  delete watched_cells;
+}
+
+
+void
+cl_hw::new_hw_adding(class cl_hw *new_hw)
+{
+}
+
+void
+cl_hw::new_hw_added(class cl_hw *new_hw)
+{
+  int i;
+
+  for (i= 0; i < partners->count; i++)
+    {
+      class cl_partner_hw *ph= (class cl_partner_hw *)(partners->at(i));
+      ph->refresh(new_hw);
+    }
+}
+
+class cl_hw *
+cl_hw::make_partner(enum hw_cath cath, int id)
+{
+  class cl_partner_hw *ph;
+  class cl_hw *hw;
+
+  ph= new cl_partner_hw(uc, cath, id);
+  partners->add(ph);
+  hw= ph->get_partner();
+  return(hw);
 }
 
 
@@ -58,17 +174,85 @@ cl_hw::~cl_hw(void)
  * Callback functions for changing memory locations
  */
 
-ulong
-cl_hw::read(class cl_mem *mem, long addr)
+/*t_mem
+cl_hw::read(class cl_m *mem, t_addr addr)
 {
   // Simply return the value
   return(mem->get(addr));
+}*/
+
+/*void
+cl_hw::write(class cl_m *mem, t_addr addr, t_mem *val)
+{
+  // Do not change *val by default
+}*/
+
+void
+cl_hw::set_cmd(class cl_cmdline *cmdline, class cl_console_base *con)
+{
+  con->dd_printf("Nothing to do\n");
+}
+
+class cl_memory_cell *
+cl_hw::register_cell(class cl_address_space *mem, t_addr addr,
+                     class cl_memory_cell **store,
+                     enum what_to_do_on_cell_change awtd)
+{
+  class cl_watched_cell *wc;
+  class cl_memory_cell *cell;
+
+  if (mem)
+    mem->register_hw(addr, this, (int*)0, DD_FALSE);
+  else
+    printf("regcell JAJ no mem\n");
+  wc= new cl_watched_cell(mem, addr, &cell, awtd);
+  if (store)
+    *store= cell;
+  watched_cells->add(wc);
+  // announce
+  //uc->sim->mem_cell_changed(mem, addr);
+  return(cell);
+}
+
+class cl_memory_cell *
+cl_hw::use_cell(class cl_address_space *mem, t_addr addr,
+                class cl_memory_cell **store,
+                enum what_to_do_on_cell_change awtd)
+{
+  class cl_watched_cell *wc;
+  class cl_memory_cell *cell;
+
+  wc= new cl_used_cell(mem, addr, &cell, awtd);
+  if (store)
+    *store= cell;
+  watched_cells->add(wc);
+  return(cell);
 }
 
 void
-cl_hw::write(class cl_mem *mem, long addr, ulong *val)
+cl_hw::mem_cell_changed(class cl_address_space *mem, t_addr addr)
 {
-  // Do not change *val by default
+  int i;
+
+  for (i= 0; i < watched_cells->count; i++)
+    {
+      class cl_watched_cell *wc=
+        (class cl_watched_cell *)(watched_cells->at(i));
+      wc->mem_cell_changed(mem, addr, this);
+    }
+}
+
+void
+cl_hw::address_space_added(class cl_address_space *as)
+{
+  int i;
+
+  for (i= 0; i < watched_cells->count; i++)
+    {
+      class cl_watched_cell *wc=
+        dynamic_cast<class cl_watched_cell *>(watched_cells->object_at(i));
+      wc->address_space_added(as, this);
+    }
 }
 
 
@@ -83,9 +267,138 @@ cl_hw::tick(int cycles)
 }
 
 void
-cl_hw::print_info(class cl_console *con)
+cl_hw::inform_partners(enum hw_event he, void *params)
+{
+  int i;
+
+  for (i= 0; i < partners->count; i++)
+    {
+      class cl_partner_hw *ph= (class cl_partner_hw *)(partners->at(i));
+      ph->happen(this, he, params);
+    }
+}
+
+
+void
+cl_hw::print_info(class cl_console_base *con)
+{
+  con->dd_printf("%s[%d]\n", id_string, id);
+}
+
+
+t_index
+cl_hws::add(void *item)
+{
+  int i;
+  t_index res;
+
+  // pre-add
+  for (i= 0; i < count; i++)
+    {
+      class cl_hw *hw= (class cl_hw *)(at(i));
+      hw->new_hw_adding((class cl_hw *)item);
+    }
+  // add
+  res= cl_list::add(item);
+  // post-add
+  for (i= 0; i < count; i++)
+    {
+      class cl_hw *hw= (class cl_hw *)(at(i));
+      hw->new_hw_added((class cl_hw *)item);
+    }
+  ((class cl_hw *)item)->added_to_uc();
+  return(res);
+}
+
+
+void
+cl_hws::mem_cell_changed(class cl_address_space *mem, t_addr addr)
+{
+  int i;
+  
+  for (i= 0; i < count; i++)
+    {
+      class cl_hw *hw= (class cl_hw *)(at(i));
+      hw->mem_cell_changed(mem, addr);
+    }
+}
+
+void
+cl_hws::address_space_added(class cl_address_space *mem)
+{
+  int i;
+  
+  for (i= 0; i < count; i++)
+    {
+      class cl_hw *hw= (class cl_hw *)(at(i));
+      hw->address_space_added(mem);
+    }
+}
+
+
+/*
+ *____________________________________________________________________________
+ */
+
+cl_partner_hw::cl_partner_hw(class cl_uc *auc, enum hw_cath cath, int aid):
+  cl_base()
+{
+  uc= auc;
+  cathegory= cath;
+  id= aid;
+  partner= uc->get_hw(cathegory, id, 0);
+}
+
+class cl_hw *
+cl_partner_hw::get_partner(void)
+{
+  return(partner);
+}
+
+void
+cl_partner_hw::refresh(void)
+{
+  class cl_hw *hw= uc->get_hw(cathegory, id, 0);
+
+  if (!hw)
+    return;
+  if (partner)
+    {
+      // partner is already set
+      if (partner != hw)
+        {
+          // partner changed?
+          partner= hw;
+        }
+      else
+        partner= hw;
+    }
+  partner= hw;
+}
+
+void
+cl_partner_hw::refresh(class cl_hw *new_hw)
+{
+  if (!new_hw)
+    return;
+  if (cathegory == new_hw->cathegory &&
+      id == new_hw->id)
+    {
+      if (partner)
+        {
+          // partner changed?
+          partner= new_hw;
+        }
+      else
+        partner= new_hw;
+    }
+}
+
+void
+cl_partner_hw::happen(class cl_hw *where, enum hw_event he, void *params)
 {
-  con->printf("%s[%d]\n", id_string, id);
+  if (partner)
+    partner->happen(where, he, params);
 }