diff options
author | Guillaume Seguin <guillaume@segu.in> | 2008-12-10 18:51:06 +0100 |
---|---|---|
committer | Guillaume Seguin <guillaume@segu.in> | 2008-12-10 18:51:06 +0100 |
commit | b69bd2c0445fba72e34dbea9860c777b3693b5c7 (patch) | |
tree | 0cafabc723e3e72048acb0b0e6415755bc20b017 | |
parent | db31e6558492a5d64aa3e9c36479e76428a99afe (diff) | |
parent | c9176fffe77acc381624ea0702cb59692b7c5232 (diff) | |
download | sysdigit-master.tar.gz sysdigit-master.tar.bz2 |
Merge branch 'master' of git+ssh://ulminfo.aulo.in/home/ixce/sysdigitmaster
-rw-r--r-- | circuitbuilder/app.py | 49 | ||||
-rw-r--r-- | circuitbuilder/builder.py | 205 | ||||
-rw-r--r-- | circuitbuilder/builder_widget.py | 147 | ||||
-rw-r--r-- | circuitbuilder/circuitbuilder.glade | 266 | ||||
-rw-r--r-- | circuitbuilder/components.py | 250 | ||||
-rw-r--r-- | circuitbuilder/constants.py | 15 | ||||
-rw-r--r-- | circuitbuilder/dialogs.py | 23 | ||||
-rw-r--r-- | circuitbuilder/scriptingwrapper.py | 20 | ||||
-rw-r--r-- | circuitbuilder/scripts/link-base | 2 | ||||
-rw-r--r-- | circuitbuilder/undoredo.py | 2 | ||||
-rw-r--r-- | circuitbuilder/viewer_widget.py | 27 | ||||
-rw-r--r-- | circuitbuilder/xmlhandling.py | 20 | ||||
-rw-r--r-- | simul/Makefile | 15 | ||||
-rw-r--r-- | simul/compil.ml | 96 | ||||
-rw-r--r-- | simul/fulladder.xnl | 33 | ||||
-rw-r--r-- | simul/lexerPaths.ml | 127 | ||||
-rw-r--r-- | simul/lexerPaths.mll | 17 | ||||
-rw-r--r-- | simul/main.ml | 35 | ||||
-rwxr-xr-x | simul/maketest | 7 | ||||
-rw-r--r-- | simul/paths | 2 | ||||
-rwxr-xr-x | utils/tick.c | 14 | ||||
-rw-r--r-- | utils/tick.cpp | 60 |
22 files changed, 1205 insertions, 227 deletions
diff --git a/circuitbuilder/app.py b/circuitbuilder/app.py new file mode 100644 index 0000000..0d4a90e --- /dev/null +++ b/circuitbuilder/app.py @@ -0,0 +1,49 @@ +import glob +import os.path +import xmlhandling +from dialogs import open_dialog + +class CircuitApp(object): + + def open_circuit_internal(self, file = None): + if not file: + file = open_dialog(self.window) + if not file: + return None, None + f = open(file) + data = xmlhandling.parse_xml(f, self.component_factory) + f.close() + return file, data + + def load_all_components(self, paths): + for path in paths: + components = glob.glob(os.path.join(path, "*.xnl")) + for component in components: + f = open(component) + data = xmlhandling.parse_component_head(f) + f.close() + self.load_component_real(data) + + def load_component(self, *args): + data = self.load_component_internal() + if not data: + self.push_status("Impossible de charger ce composant") + return + self.load_component_real(data) + + def load_component_internal(self, searched_name = None): + if searched_name: + dialog_title = "Charger le composant %s..." % searched_name + else: + dialog_title = "Charger un composant..." + file = open_dialog(self.window, title = dialog_title) + if not file: + return + f = open(file) + data = xmlhandling.parse_component_head(f) + f.close() + return data + + def load_component_real(self, data): + component_type = self.component_factory.create_component_type(*data) + self.component_factory.register_component_type(component_type) diff --git a/circuitbuilder/builder.py b/circuitbuilder/builder.py index 910adfe..d1e2d15 100644 --- a/circuitbuilder/builder.py +++ b/circuitbuilder/builder.py @@ -27,6 +27,8 @@ pygtk.require ('2.0') import gobject import gtk import gtk.glade +import pango +import gtksourceview2 import sys import os.path @@ -36,6 +38,7 @@ from builder_widget import CircuitBuilderWidget from selector_widget import ComponentSelector from status_handler import StatusHandler from undoredo import UndoRedoStack, UndoRedoAction +from scriptingwrapper import ScriptingWrapper from constants import * @@ -43,10 +46,11 @@ import components from link import Link from dialogs import open_dialog, save_dialog import xmlhandling +from app import CircuitApp from shared import autoconnect -class CircuitBuilder(object): +class CircuitBuilder(CircuitApp): glade = None @@ -56,6 +60,8 @@ class CircuitBuilder(object): status_handler = None undo_redo_stack = None + script_buffer = None + component_factory = None __toolbar_toggles_group = None @@ -96,6 +102,7 @@ class CircuitBuilder(object): self.__fill_toolbar_toggles_group() self.__add_dialogs_buttons() self.__init_select_link_treeview() + self.__init_script_dialog() self.can_undo = False self.can_redo = False @@ -108,12 +115,52 @@ class CircuitBuilder(object): column = gtk.TreeViewColumn("Lien", text_renderer, text = 1) treeview.append_column(column) + def __init_script_dialog(self): + language_manager = gtksourceview2.language_manager_get_default() + language = language_manager.get_language(EDITOR_LANGUAGE) + style_manager = gtksourceview2.style_scheme_manager_get_default() + style_scheme = style_manager.get_scheme(EDITOR_STYLE) + self.script_buffer = gtksourceview2.Buffer() + self.script_buffer.set_language(language) + self.script_buffer.set_style_scheme(style_scheme) + sourceview = gtksourceview2.View(self.script_buffer) + sourceview.set_auto_indent(True) + sourceview.set_indent_on_tab(True) + sourceview.set_indent_width(4) + sourceview.set_tab_width(4) + sourceview.set_insert_spaces_instead_of_tabs(True) + sourceview.set_wrap_mode(gtk.WRAP_WORD) + font_desc = pango.FontDescription("Monospace 10") + sourceview.modify_font(font_desc) + sourceview.show() + window = self.glade.get_widget("scriptSourceViewWindow") + window.add(sourceview) + model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) + treeview = self.glade.get_widget("scriptsTreeView") + treeview.set_model(model) + text_renderer = gtk.CellRendererText () + column = gtk.TreeViewColumn("Script", text_renderer, text = 1) + treeview.append_column(column) + self.__load_scripts() + + def __load_scripts(self): + treeview = self.glade.get_widget("scriptsTreeView") + model = treeview.get_model() + model.clear() + if not os.path.exists("scripts"): + return + files = os.listdir("scripts") + for file in files: + path = os.path.join("scripts", file) + f = open(path) + script = f.read() + f.close() + model.append((script, file)) + def reset(self): - components.Component.auto_id = 1 - components.Input.auto_input_id = 1 - components.Output.auto_output_id = 1 self.__toolbar_toggle_others(None) self.__switch_select_boxes_visibility(PROPERTIES_COMPONENT_MODE) + self.component_factory.reset() self.builder_widget.reset() self.selector_widget.reset() self.undo_redo_stack.reset() @@ -178,7 +225,8 @@ class CircuitBuilder(object): saved = property(_get_saved, _set_saved) def __fill_toolbar_toggles_group(self): - widgets = ["select", "addGate", "delGate", "addLink", "delLink"] + widgets = ["select", "addGate", "moveGate", "scriptGates", "delGate", + "addLink", "delLink"] self.__toolbar_toggles_group = [self.glade.get_widget(w + "Button") \ for w in widgets] @@ -189,7 +237,8 @@ class CircuitBuilder(object): dialog.ok_button = dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) for dialog in ("setComponentDialog", "setLinkDialog", "resizeDialog", - "defineCircuitDialog", "selectLinkDialog"): + "defineCircuitDialog", "selectLinkDialog", + "scriptDialog"): dialog = self.glade.get_widget(dialog) process_dialog(dialog) @@ -214,28 +263,34 @@ class CircuitBuilder(object): inputs_hbox.hide() if hasattr(component, "input_id"): input_id_hbox.show() - input_id_spin.set_range(1, component.max_input_id) + input_id_spin.set_range(1, component.pool.max_input_id) input_id_spin.set_value(component.input_id) else: input_id_hbox.hide() if hasattr(component, "output_id"): output_id_hbox.show() - output_id_spin.set_range(1, component.max_output_id) + output_id_spin.set_range(1, component.pool.max_output_id) output_id_spin.set_value(component.output_id) else: output_id_hbox.hide() dialog.ok_button.grab_default() response = dialog.run() - self.hide_widget(dialog) + dialog.hide() if response != gtk.RESPONSE_OK: return None component.id = id_entry.get_text() if not component.fixed_inputs: - component.inputs = inputs_spin.get_value() + component.inputs = int(inputs_spin.get_value()) if hasattr(component, "input_id"): - component.input_id = input_id_spin.get_value() + new_input_id = int(input_id_spin.get_value()) + if new_input_id != component.input_id: + component.input_id = new_input_id + self.builder_widget.redraw_surface() if hasattr(component, "output_id"): - component.output_id = output_id_spin.get_value() + new_output_id = int(output_id_spin.get_value()) + if new_output_id != component.output_id: + component.output_id = new_output_id + self.builder_widget.redraw_surface() self.saved = False return component @@ -254,7 +309,7 @@ class CircuitBuilder(object): return None else: output_id_spin.set_range(1, start.outputs) - output_id_spin.set_value(1) + output_id_spin.set_value(start.first_available_output) output_id_hbox.show() if end.inputs == 1: input_id = 1 @@ -263,19 +318,27 @@ class CircuitBuilder(object): # FIXME : verbose me! return None else: + default_input_id = end.first_available_input + if default_input_id == -1: + # FIXME : verbose me! + return None input_id_spin.set_range(1, end.inputs) - input_id_spin.set_value(1) + input_id_spin.set_value(default_input_id) input_id_hbox.show() if not output_id or not input_id: dialog.ok_button.grab_default() response = dialog.run() - self.hide_widget(dialog) + dialog.hide() if response != gtk.RESPONSE_OK: return None if start.outputs != 1: output_id = output_id_spin.get_value() if end.inputs != 1: input_id = input_id_spin.get_value() + used_inputs = [link.input_id for link in end.parent_links] + if input_id in used_inputs: + # FIXME : verbose me! + return None link = Link(start, output_id, end, input_id) self.saved = False return link @@ -310,12 +373,9 @@ class CircuitBuilder(object): self.reset() def open_circuit(self, *args): - file = open_dialog(self.window) - if not file: + file, data = self.open_circuit_internal() + if data == False: return - f = open(file) - data = xmlhandling.parse_xml(f, self.component_factory) - f.close() if not data: self.push_status("Impossible de charger ce circuit") return @@ -329,39 +389,6 @@ class CircuitBuilder(object): min_height) self.builder_widget.components = components - def load_all_components(self, paths): - for path in paths: - components = glob.glob(os.path.join(path, "*.xnl")) - for component in components: - f = open(component) - data = xmlhandling.parse_component_head(f) - f.close() - self.load_component_real(data) - - def load_component(self, *args): - data = self.load_component_internal() - if not data: - self.push_status("Impossible de charger ce composant") - return - self.load_component_real(data) - - def load_component_internal(self, searched_name = None): - if searched_name: - dialog_title = "Charger le composant %s..." % searched_name - else: - dialog_title = "Charger un composant..." - file = open_dialog(self.window, title = dialog_title) - if not file: - return - f = open(file) - data = xmlhandling.parse_component_head(f) - f.close() - return data - - def load_component_real(self, data): - component_type = self.component_factory.create_component_type(*data) - self.component_factory.register_component_type(component_type) - def save_circuit(self, *args): if not self.__filename: self.save_circuit_as() @@ -391,7 +418,7 @@ class CircuitBuilder(object): symbol_entry.set_text("") dialog.ok_button.grab_default() response = dialog.run() - self.hide_widget(dialog) + dialog.hide() if response != gtk.RESPONSE_OK: return None self.name = name_entry.get_text() @@ -420,7 +447,7 @@ class CircuitBuilder(object): heightSpin.set_value(self.builder_widget.height) dialog.ok_button.grab_default() response = dialog.run() - self.hide_widget(dialog) + dialog.hide() if response != gtk.RESPONSE_OK: return None self.builder_widget.width = int(widthSpin.get_value()) @@ -450,6 +477,9 @@ class CircuitBuilder(object): PROPERTIES_LINK_MODE) def choose_link(self, links): + def link_cmp(l1, l2): + return cmp(str(l1), str(l2)) + links.sort(cmp = link_cmp) dialog = self.glade.get_widget("selectLinkDialog") treeview = self.glade.get_widget("selectLinkDialogTreeView") model = treeview.get_model() @@ -458,7 +488,7 @@ class CircuitBuilder(object): model.append((link, str(link))) dialog.ok_button.grab_default() response = dialog.run() - self.hide_widget(dialog) + dialog.hide() if response != gtk.RESPONSE_OK: return None _, iter = treeview.get_selection().get_selected() @@ -574,6 +604,49 @@ class CircuitBuilder(object): output_spin.set_value(link.output_id) self.selected_link = link + def script(self): + components = self.builder_widget.scripted_components + dialog = self.glade.get_widget("scriptDialog") + components_label = self.glade.get_widget("componentsCountValueLabel") + components_label.set_text("%d" % len(components)) + dialog.ok_button.grab_default() + response = dialog.run() + dialog.hide() + if response != gtk.RESPONSE_OK: + return None + script = self.script_buffer.get_text(*self.script_buffer.get_bounds()) + script = script.strip() + if not script: + return None + compiled_script = compile(script, "<string>", "exec") + exec compiled_script in {"components": components, + "builder": ScriptingWrapper(self)} + + def save_script(self, *args): + filename = save_dialog(self.window, ext = "") + if not filename: + return + f = open(filename, "w") + data = self.script_buffer.get_text(*self.script_buffer.get_bounds()) + f.write(data) + f.close() + self.__load_scripts() + + def select_script(self, treeview, path, view_column): + model = treeview.get_model() + iter = model.get_iter(path) + data = model.get_value(iter, 0) + self.script_buffer.set_text(data) + + def launch_script_dialog(self, *args): + self.script() + + def reset_selections(self, *args): + self.builder_widget.reset_add_link() + self.builder_widget.reset_move_gate() + self.builder_widget.reset_script_gates() + self.builder_widget.queue_draw() + def set_select_mode(self, widget, *args): if widget.get_active(): self.__toolbar_toggle_others(widget) @@ -589,6 +662,20 @@ class CircuitBuilder(object): self.__toolbar_toggle_others(widget) self.builder_widget.action = BUILDER_ACTION_ADD_GATE + def set_move_gate_mode(self, widget, *args): + if widget.get_active(): + self.__toolbar_toggle_others(widget) + self.builder_widget.action = BUILDER_ACTION_MOVE_GATE + else: + self.builder_widget.reset_move_gate() + + def set_script_gates_mode(self, widget, *args): + if widget.get_active(): + self.__toolbar_toggle_others(widget) + self.builder_widget.action = BUILDER_ACTION_SCRIPT_GATES + else: + self.builder_widget.reset_script_gates() + def set_del_gate_mode(self, widget, *args): if widget.get_active(): self.__toolbar_toggle_others(widget) @@ -612,6 +699,12 @@ class CircuitBuilder(object): def toggle_add_gate_mode(self, *args): self.glade.get_widget("addGateButton").set_active(True) + def toggle_move_gate_mode(self, *args): + self.glade.get_widget("moveGateButton").set_active(True) + + def toggle_script_gates_mode(self, *args): + self.glade.get_widget("scriptGatesButton").set_active(True) + def toggle_del_gate_mode(self, *args): self.glade.get_widget("delGateButton").set_active(True) diff --git a/circuitbuilder/builder_widget.py b/circuitbuilder/builder_widget.py index 6b70ca9..ba42fa6 100644 --- a/circuitbuilder/builder_widget.py +++ b/circuitbuilder/builder_widget.py @@ -30,16 +30,36 @@ import cairo from constants import * from undoredo import UndoRedoAction -from viewer_widget import CircuitViewerWidget +from viewer_widget import CircuitViewerWidget, dist class CircuitBuilderWidget(CircuitViewerWidget): __first_link_component = None + __moving_component_surface = None + __moving_component = None + scripted_components = None def __init__(self, parent, *args, **kwargs): super(CircuitBuilderWidget, self).__init__(parent, *args, **kwargs) + self.__moving_component_surface = \ + cairo.ImageSurface(cairo.FORMAT_ARGB32, PART_SIZE, PART_SIZE) self.connect("motion-notify-event", self.__motion_notify_cb) self.connect("button-press-event", self.__button_press_cb) + self.scripted_components = [] + + def __can_move(self, x, y): + (c_x, c_y) = self.__moving_component.x, self.__moving_component.y + for (i, j) in self._components_keys: + if (i, j) == (c_x, c_y): + continue + if i > x + PART_SIZE: + return True + if i < x - PART_SIZE or abs(j - y) > PART_SIZE: + continue + if dist(i, j, x, y) > PART_SIZE: + continue + return False + return True def __can_add(self, x, y): for (i, j) in self._components_keys: @@ -47,6 +67,8 @@ class CircuitBuilderWidget(CircuitViewerWidget): return True if i < x - PART_SIZE or abs(j - y) > PART_SIZE: continue + if dist(i, j, x, y) > PART_SIZE: + continue return False return True @@ -63,6 +85,7 @@ class CircuitBuilderWidget(CircuitViewerWidget): def restore_component(self, component): self.add_component(component) + component.add_to_pool() restored_links = component.restore_links() for link in restored_links: self.add_link(link) @@ -77,6 +100,7 @@ class CircuitBuilderWidget(CircuitViewerWidget): component.x = x component.y = y if not self._parent.set_component(component): + component.drop_from_pool() self._parent.push_status("Création du composant annulée") return self.add_component(component) @@ -85,16 +109,48 @@ class CircuitBuilderWidget(CircuitViewerWidget): self._parent.undo_redo_stack.add_to_stack(action) self._parent.push_status("Composant ajouté") + def __move_component_at(self, x, y): + if not self.__moving_component: + component = self._get_component_at(x, y) + if component: + self.__moving_component = component + self._make_component_surface(self.__moving_component_surface, + self.__moving_component) + return + x, y = self._translate_middle_coords(x, y) + if self.__can_move(x, y): + component = self.__moving_component + x0, y0 = component.x, component.y + component.x, component.y = x, y + del self._components[x0, y0] + self._components_keys.remove((x0, y0)) + self._components[(x, y)] = component + self._components_keys.append((x, y)) + self._components_keys.sort() + for link in component.parent_links + component.child_links: + del self._links_squares[link] + start = link.output_gate + end = link.input_gate + self._links_squares[link] = self._get_link_square(start, end) + self.redraw_surface() + self.__moving_component = None + + def __script_component_at(self, x, y): + component = self._get_component_at(x, y) + if not component: + return + self.scripted_components.append(component) + def del_component(self, component): x, y = component.x, component.y self._components_keys.remove((x, y)) del self._components[(x, y)] component.destroy_links() + component.drop_from_pool() for link in self._links_squares.keys(): if component in (link.output_gate, link.input_gate): del self._links_squares[link] - self._redraw_surface() - self.queue_draw() + self.redraw_surface() def __del_component_at(self, x, y): component = self._get_component_at(x, y) @@ -139,18 +195,20 @@ différents''') if not link: self._parent.push_status("Création du lien annulée") return - self.add_link(link) - action = UndoRedoAction(action = ACTION_ADD_LINK, link = link) - self._parent.undo_redo_stack.add_to_stack(action) + self.add_link_internal(link) # Reset add link process self.reset_add_link() self._parent.push_status("Lien ajouté") + def add_link_internal(self, link): + self.add_link(link) + action = UndoRedoAction(action = ACTION_ADD_LINK, link = link) + self._parent.undo_redo_stack.add_to_stack(action) + def del_link(self, link): link.destroy() del self._links_squares[link] - self._redraw_surface() - self.queue_draw() + self.redraw_surface() def __del_link_at(self, x, y): link = self._get_link_at(x, y) @@ -163,6 +221,32 @@ différents''') self._parent.push_status("Lien supprimé") def _update_overlay(self, cr): + def draw_gate_op_attempt(x0, y0, surface, color): + cr.save() + cr.rectangle(x0, y0, PART_SIZE, PART_SIZE) + cr.clip() + cr.set_source_rgb(*color) + cr.mask_surface(surface, x0, y0) + cr.set_operator(cairo.OPERATOR_OVER) + cr.stroke() + cr.restore() + def draw_gate_add_attempt(): + x0, y0 = self._translate_middle_coords(self._current_x, + self._current_y) + if self.__can_add(x0, y0): + color = OK_COLOR + else: + color = NOTOK_COLOR + draw_gate_op_attempt(x0, y0, self._component_surface, color) + def draw_gate_move_attempt(): + x0, y0 = self._translate_middle_coords(self._current_x, + self._current_y) + if self.__can_move(x0, y0): + color = OK_COLOR + else: + color = NOTOK_COLOR + draw_gate_op_attempt(x0, y0, self.__moving_component_surface, + color) if self._current_x == -1: return x0 = self._current_x @@ -186,18 +270,31 @@ différents''') for link in links: self._overlay_link(cr, link, AUDIT_COLOR) elif self.action == BUILDER_ACTION_ADD_GATE: - x0, y0 = self._translate_middle_coords(x0, y0) - cr.save() - cr.rectangle(x0, y0, PART_SIZE, PART_SIZE) - cr.clip() - if self.__can_add(x0, y0): - color = OK_COLOR + draw_gate_add_attempt() + elif self.action == BUILDER_ACTION_MOVE_GATE: + if self.__moving_component: + cr.save() + self._overlay_component(cr, self.__moving_component, OK_COLOR) + cr.restore() + draw_gate_move_attempt() else: - color = NOTOK_COLOR - cr.set_source_rgb(*color) - cr.mask_surface(self._component_surface, x0, y0) - cr.set_operator(cairo.OPERATOR_OVER) - cr.stroke() + component = self._get_component_at(x0, y0) + if not component: + return + cr.save() + self._overlay_component(cr, component, OK_COLOR) + cr.restore() + elif self.action == BUILDER_ACTION_SCRIPT_GATES: + if self.scripted_components: + for component in self.scripted_components: + cr.save() + self._overlay_component(cr, component, OK_COLOR) + cr.restore() + component = self._get_component_at(x0, y0) + if not component: + return + cr.save() + self._overlay_component(cr, component, OK_COLOR) cr.restore() elif self.action == BUILDER_ACTION_DEL_GATE: component = self._get_component_at(x0, y0) @@ -230,6 +327,12 @@ différents''') def reset_add_link(self): self.__first_link_component = None + def reset_move_gate(self): + self.__moving_component = None + + def reset_script_gates(self): + self.scripted_components = [] + def __button_press_cb(self, widget, event): if self.action == BUILDER_ACTION_SELECT: x0, y0 = event.x, event.y @@ -237,6 +340,12 @@ différents''') elif self.action == BUILDER_ACTION_ADD_GATE: x0, y0 = self._translate_middle_coords(event.x, event.y) self.__add_component_at(x0, y0) + elif self.action == BUILDER_ACTION_MOVE_GATE: + x0, y0 = event.x, event.y + self.__move_component_at(x0, y0) + elif self.action == BUILDER_ACTION_SCRIPT_GATES: + x0, y0 = event.x, event.y + self.__script_component_at(x0, y0) elif self.action == BUILDER_ACTION_DEL_GATE: x0, y0 = event.x, event.y self.__del_component_at(x0, y0) diff --git a/circuitbuilder/circuitbuilder.glade b/circuitbuilder/circuitbuilder.glade index 8a0e739..8ba4c1f 100644 --- a/circuitbuilder/circuitbuilder.glade +++ b/circuitbuilder/circuitbuilder.glade @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> -<!--Generated with glade3 3.4.5 on Mon Nov 3 04:09:08 2008 --> +<!--Generated with glade3 3.4.5 on Sat Nov 8 01:38:09 2008 --> <glade-interface> <widget class="GtkWindow" id="mainWindow"> <property name="title" translatable="yes">Logic Circuit Builder</property> <property name="window_position">GTK_WIN_POS_CENTER</property> - <property name="default_width">700</property> - <property name="default_height">500</property> + <property name="default_width">800</property> + <property name="default_height">600</property> <signal name="delete_event" handler="gtk_main_quit"/> <child> <widget class="GtkVBox" id="mainVBox"> @@ -128,7 +128,7 @@ <child> <widget class="GtkImageMenuItem" id="selectMenuItem"> <property name="visible">True</property> - <property name="label" translatable="yes">gtk-properties</property> + <property name="label" translatable="yes">gtk-info</property> <property name="use_underline">True</property> <property name="use_stock">True</property> <signal name="activate" handler="toggle_select_mode"/> @@ -151,6 +151,36 @@ </widget> </child> <child> + <widget class="GtkImageMenuItem" id="moveMenuItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">Déplacer</property> + <property name="use_underline">True</property> + <signal name="activate" handler="toggle_move_gate_mode"/> + <accelerator key="M" modifiers="GDK_CONTROL_MASK" signal="activate"/> + <child internal-child="image"> + <widget class="GtkImage" id="menu-item-image4"> + <property name="visible">True</property> + <property name="stock">gtk-jump-to</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="scriptGatesMenuItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">Scripter des portes</property> + <property name="use_underline">True</property> + <signal name="activate" handler="toggle_script_gates_mode"/> + <accelerator key="W" modifiers="GDK_CONTROL_MASK" signal="activate"/> + <child internal-child="image"> + <widget class="GtkImage" id="menu-item-image5"> + <property name="visible">True</property> + <property name="stock">gtk-index</property> + </widget> + </child> + </widget> + </child> + <child> <widget class="GtkImageMenuItem" id="delGateMenuItem"> <property name="visible">True</property> <property name="label" translatable="yes">gtk-remove</property> @@ -195,6 +225,41 @@ </widget> </child> <child> + <widget class="GtkImageMenuItem" id="scriptMenuItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">Scripter</property> + <property name="use_underline">True</property> + <signal name="activate" handler="launch_script_dialog"/> + <accelerator key="X" modifiers="GDK_CONTROL_MASK" signal="activate"/> + <child internal-child="image"> + <widget class="GtkImage" id="menu-item-image6"> + <property name="visible">True</property> + <property name="stock">gtk-edit</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="resetMenuItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">Réinitialiser la sélection</property> + <property name="use_underline">True</property> + <signal name="activate" handler="reset_selections"/> + <accelerator key="Escape" modifiers="" signal="activate"/> + <child internal-child="image"> + <widget class="GtkImage" id="menu-item-image7"> + <property name="visible">True</property> + <property name="stock">gtk-cancel</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkSeparatorMenuItem" id="editMenuSeparator5"> + <property name="visible">True</property> + </widget> + </child> + <child> <widget class="GtkImageMenuItem" id="resizeMenuItem"> <property name="visible">True</property> <property name="label" translatable="yes">Élargir le circuit</property> @@ -280,7 +345,7 @@ <property name="visible">True</property> <property name="has_tooltip">True</property> <property name="tooltip_text">Sélectionner un composant ou un lien</property> - <property name="stock_id">gtk-properties</property> + <property name="stock_id">gtk-info</property> <signal name="toggled" handler="set_select_mode"/> </widget> <packing> @@ -308,6 +373,30 @@ </packing> </child> <child> + <widget class="GtkToggleToolButton" id="moveGateButton"> + <property name="visible">True</property> + <property name="tooltip_text">Déplacer un composant</property> + <property name="label" translatable="yes">Déplacer</property> + <property name="stock_id">gtk-jump-to</property> + <signal name="toggled" handler="set_move_gate_mode"/> + </widget> + <packing> + <property name="homogeneous">True</property> + </packing> + </child> + <child> + <widget class="GtkToggleToolButton" id="scriptGatesButton"> + <property name="visible">True</property> + <property name="tooltip_text">Scripter des composants</property> + <property name="label" translatable="yes">Scripter des portes</property> + <property name="stock_id">gtk-index</property> + <signal name="toggled" handler="set_script_gates_mode"/> + </widget> + <packing> + <property name="homogeneous">True</property> + </packing> + </child> + <child> <widget class="GtkToggleToolButton" id="delGateButton"> <property name="visible">True</property> <property name="has_tooltip">True</property> @@ -351,6 +440,25 @@ <property name="homogeneous">True</property> </packing> </child> + <child> + <widget class="GtkSeparatorToolItem" id="toolbarSeparator4"> + <property name="visible">True</property> + </widget> + <packing> + <property name="homogeneous">True</property> + </packing> + </child> + <child> + <widget class="GtkToolButton" id="scriptButton"> + <property name="visible">True</property> + <property name="tooltip_text">Scripter</property> + <property name="stock_id">gtk-edit</property> + <signal name="clicked" handler="launch_script_dialog"/> + </widget> + <packing> + <property name="homogeneous">True</property> + </packing> + </child> </widget> <packing> <property name="expand">False</property> @@ -361,7 +469,7 @@ <widget class="GtkHPaned" id="mainPaned"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="position">500</property> + <property name="position">600</property> <child> <widget class="GtkScrolledWindow" id="builderWindow"> <property name="visible">True</property> @@ -1286,4 +1394,150 @@ </widget> </child> </widget> + <widget class="GtkDialog" id="scriptDialog"> + <property name="border_width">5</property> + <property name="title" translatable="yes">Sélection du script</property> + <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> + <property name="default_width">700</property> + <property name="default_height">500</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="has_separator">False</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox11"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkHPaned" id="scriptDialogHPaned"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">520</property> + <child> + <widget class="GtkVBox" id="scriptDialogVBox"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="componentsCountHBox"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="componentsCountLabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">Portes sélectionnées : </property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="componentsCountValueLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="scriptSourceViewWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="scriptSaveAlignment"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <property name="top_padding">5</property> + <property name="right_padding">5</property> + <child> + <widget class="GtkButton" id="scriptSaveButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="label" translatable="yes">gtk-save</property> + <property name="use_stock">True</property> + <property name="response_id">0</property> + <signal name="clicked" handler="save_script"/> + <accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="clicked"/> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="resize">False</property> + <property name="shrink">True</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="scriptsVBox"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="scriptsLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Scripts disponibles :</property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkTreeView" id="scriptsTreeView"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <signal name="row_activated" handler="select_script"/> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="resize">True</property> + <property name="shrink">True</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area11"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + </widget> </glade-interface> diff --git a/circuitbuilder/components.py b/circuitbuilder/components.py index d0accad..5eff5de 100644 --- a/circuitbuilder/components.py +++ b/circuitbuilder/components.py @@ -23,7 +23,7 @@ class Component(object): auto_id = 1 - id = "" + _id = None symbol = "" outputs = 1 @@ -45,8 +45,10 @@ class Component(object): outputs_status = None - def __init__(self): - self.id = "g%d" % Component.auto_id + pool = None + + def __init__(self, **kwargs): + self._id = "g%d" % Component.auto_id Component.auto_id += 1 self.parent_links = [] self.child_links = [] @@ -54,10 +56,58 @@ class Component(object): self.outputs_status = {} if self.fixed_inputs: self.min_inputs = self.max_inputs = self.inputs + for attr in kwargs: + setattr(self, attr, kwargs[attr]) + self.add_to_pool() def __str__(self): return "[%s %s]" % (self.__class__.__name__, self.id) + def _set_component_id(self, id): + old_id, self._id = self._id, id + self.pool.set_component_id(self, old_id) + + def _get_component_id(self): + return self._id + + id = property(_get_component_id, _set_component_id) + + def add_to_pool(self): + self.pool.register_component(self) + + def drop_from_pool(self): + self.pool.unregister_component(self) + + def links_to(self, end): + def check_end(link): + return link.input_gate == end + return filter(check_end, self.child_links) + + def links_from(self, start): + def check_start(link): + return link.output_gate == end + return filter(check_start, self.parent_links) + + def _get_first_available_input(self): + used_inputs = [link.input_id for link in self.parent_links] + r = range(1, self.inputs + 1) + free_inputs = filter(lambda i: i not in used_inputs, r) + if not free_inputs: + return -1 + return free_inputs[0] + + first_available_input = property(_get_first_available_input) + + def _get_first_available_output(self): + used_outputs = [link.output_id for link in self.child_links] + r = range(1, self.outputs + 1) + free_outputs = filter(lambda i: i not in used_outputs, r) + if not free_outputs: + return 1 + return free_outputs[0] + + first_available_output = property(_get_first_available_output) + def add_link(self, link): if (link.output_gate == self): self.child_links.append(link) @@ -112,34 +162,54 @@ class Xor(Component): class Input(Component): symbol = "i" - auto_input_id = 1 - input_id = 0 - max_input_id = 128 + _input_id = 0 fixed_inputs = True inputs = 0 outputs = 1 - def __init__(self): - super(Input, self).__init__() - self.input_id = Input.auto_input_id - Input.auto_input_id += 1 + def add_to_pool(self): + super(Input, self).add_to_pool() + self.pool.register_input(self) + + def drop_from_pool(self): + super(Input, self).drop_from_pool() + self.pool.unregister_input(self) + + def set_input_id(self, id): + self.pool.set_input_id(self, id) + self._input_id = id + + def get_input_id(self): + return self._input_id + + input_id = property(get_input_id, set_input_id) class Output(Component): symbol = "o" - auto_output_id = 1 - output_id = 0 - max_output_id = 128 + _output_id = 0 fixed_inputs = True inputs = 1 outputs = 0 - def __init__(self): - super(Output, self).__init__() - self.output_id = Output.auto_output_id - Output.auto_output_id += 1 + def add_to_pool(self): + super(Output, self).add_to_pool() + self.pool.register_output(self) + + def drop_from_pool(self): + super(Output, self).drop_from_pool() + self.pool.unregister_output(self) + + def _set_output_id(self, id): + self.pool.set_output_id(self, id) + self._output_id = id + + def _get_output_id(self): + return self._output_id + + output_id = property(_get_output_id, _set_output_id) class Reg(Component): @@ -185,32 +255,168 @@ class Zero(Component): fixed_inputs = True inputs = 0 +class RAMR(Component): + + symbol = "RAMR" + + fixed_inputs = True + inputs = 16 + + outputs = 8 + +class RAMW(Component): + + symbol = "RAMW" + + fixed_inputs = True + inputs = 24 + + outputs = 0 + +class ROMR(Component): + + symbol = "ROMR" + + fixed_inputs = True + inputs = 16 + + outputs = 8 + DEFAULT_COMPONENT_TYPES = [Not, And, Or, Nand, Nor, Xor, Input, Output, - Reg, RegInput, RegOutput, Mux, One, Zero] + Reg, RegInput, RegOutput, Mux, One, Zero, + RAMR, RAMW, ROMR] + +class ComponentsPool(object): + + components = None + + inputs = None + outputs = None + + def __init__(self): + self.reset() + + def reset(self): + self.components = {} + self.inputs = {} + self.outputs = {} + + def register_component(self, component): + id = component.id + if id not in self.components: + self.components[id] = component + return + i = 1 + id = "%ss%d" % (component.id, i) + while id in self.components: + i += 1 + id = "%ss%d" % (component.id, i) + component._id = id + self.components[id] = component + + def register_input(self, input): + id = self.min_free_input_id + if input.input_id == 0: + input._input_id = id + self.inputs[id] = input + + def register_output(self, output): + id = self.min_free_output_id + if output.output_id == 0: + output._output_id = id + self.outputs[id] = output + + def unregister_component(self, component): + del self.components[component.id] + + def unregister_input(self, input): + del self.inputs[input.input_id] + + def unregister_output(self, output): + del self.outputs[output.output_id] + + def set_component_id(self, component, old_id): + del self.components[old_id] + self.register_component(component) + + def set_input_id(self, input, id): + if input.input_id == id: + return + if id in self.inputs: + old_input = self.inputs[id] + old_input._input_id = input.input_id + self.inputs[input.input_id] = old_input + self.inputs[id] = input + + def set_output_id(self, output, id): + if output.output_id == id: + return + if id in self.outputs: + old_output = self.outputs[id] + old_output._output_id = output.output_id + self.outputs[output.output_id] = old_output + self.outputs[id] = output + + def get_min_free_input_id(self): + ids = self.inputs.keys() + r = range(1, max(self.max_input_id + 1, len(ids) + 1) + 1) + free_ids = filter(lambda i: i not in ids, r) + return min(free_ids) + + min_free_input_id = property(get_min_free_input_id) + + def get_min_free_output_id(self): + ids = self.outputs.keys() + r = range(1, max(self.max_output_id + 1, len(ids) + 1) + 1) + free_ids = filter(lambda i: i not in ids, r) + return min(free_ids) + + min_free_output_id = property(get_min_free_output_id) + + def get_max_input_id(self): + if not self.inputs: + return 0 + return max(self.inputs.keys()) + + max_input_id = property(get_max_input_id) + + def get_max_output_id(self): + if not self.outputs: + return 0 + return max(self.outputs.keys()) + + max_output_id = property(get_max_output_id) class ComponentFactory(object): component_types = None + pool = None + __register_cb = None __component_loader = None def __init__(self, register_cb, component_loader): self.component_types = {} + self.pool = ComponentsPool() self.__register_cb = register_cb self.__component_loader = component_loader self.__register_default_types() + def reset(self): + self.pool.reset() + def __register_default_types(self): for component_type in DEFAULT_COMPONENT_TYPES: self.register_component_type(component_type) def register_component_type(self, component_type): + component_type.pool = self.pool self.component_types[component_type.__name__] = component_type if self.__register_cb: self.__register_cb(component_type) - def create_component(self, component_type): + def create_component(self, component_type, initial_data = None): if component_type not in self.component_types: data = self.__component_loader(searched_name = component_type) if not data: @@ -220,10 +426,14 @@ class ComponentFactory(object): return None component_type_class = self.create_component_type(*data) self.register_component_type(component_type_class) - return self.component_types[component_type]() + if initial_data: + return self.component_types[component_type](**initial_data) + else: + return self.component_types[component_type]() def create_component_type(self, circuit, name, symbol, inputs, outputs): component_type = type(name, (Component,), {"is_simple": False}) + component_type.pool = self.pool component_type.circuit = circuit component_type.symbol = symbol component_type.fixed_inputs = True diff --git a/circuitbuilder/constants.py b/circuitbuilder/constants.py index 121e3f8..c768273 100644 --- a/circuitbuilder/constants.py +++ b/circuitbuilder/constants.py @@ -41,11 +41,13 @@ LINK_ARROW_RAD = radians(35.0) BUILDER_MAX_WIDTH = 2000 BUILDER_MAX_HEIGHT = 2000 -BUILDER_ACTION_SELECT = 0 -BUILDER_ACTION_ADD_GATE = 1 -BUILDER_ACTION_DEL_GATE = 2 -BUILDER_ACTION_ADD_LINK = 3 -BUILDER_ACTION_DEL_LINK = 4 +BUILDER_ACTION_SELECT = 0 +BUILDER_ACTION_ADD_GATE = 1 +BUILDER_ACTION_MOVE_GATE = 2 +BUILDER_ACTION_SCRIPT_GATES = 3 +BUILDER_ACTION_DEL_GATE = 4 +BUILDER_ACTION_ADD_LINK = 5 +BUILDER_ACTION_DEL_LINK = 6 ACTION_ADD_GATE = 0 ACTION_DEL_GATE = 1 @@ -58,3 +60,6 @@ PROPERTIES_COMPONENT_MODE = 0 PROPERTIES_IN_MODE = 1 PROPERTIES_OUT_MODE = 2 PROPERTIES_LINK_MODE = 3 + +EDITOR_LANGUAGE = "python" +EDITOR_STYLE = "kate" diff --git a/circuitbuilder/dialogs.py b/circuitbuilder/dialogs.py index 0464036..6dea982 100644 --- a/circuitbuilder/dialogs.py +++ b/circuitbuilder/dialogs.py @@ -1,12 +1,13 @@ import gtk -def get_file_filters(all_files = False): +def get_file_filters(all_files = False, ext = ""): filters = [] - filter = gtk.FileFilter() - filter.set_name('.xnl') - filter.add_pattern('*.xnl') - filters.append(filter) + if ext: + filter = gtk.FileFilter() + filter.set_name(ext) + filter.add_pattern('*%s' % ext) + filters.append(filter) if all_files: filter = gtk.FileFilter() filter.set_name("Tous les fichiers") @@ -14,13 +15,13 @@ def get_file_filters(all_files = False): filters.append(filter) return filters -def file_dialog(name, action, button, parent): +def file_dialog(name, action, button, parent, ext): dialog = gtk.FileChooserDialog(name, None, action, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, button, gtk.RESPONSE_OK)) - map(dialog.add_filter, get_file_filters(all_files = True)) + map(dialog.add_filter, get_file_filters(all_files = True, ext = ext)) dialog.set_default_size(500, 300) dialog.set_position(gtk.WIN_POS_CENTER) dialog.set_icon(parent.get_icon()) @@ -32,12 +33,12 @@ def file_dialog(name, action, button, parent): dialog.destroy() return file -def open_dialog(parent, title = "Ouvrir..."): +def open_dialog(parent, title = "Ouvrir un circuit...", ext = ".xnl"): action = gtk.FILE_CHOOSER_ACTION_OPEN button = gtk.STOCK_OPEN - return file_dialog(title, action, button, parent) + return file_dialog(title, action, button, parent, ext) -def save_dialog(parent): +def save_dialog(parent, ext = ".xnl"): action = gtk.FILE_CHOOSER_ACTION_SAVE button = gtk.STOCK_SAVE - return file_dialog("Enregistrer sous...", action, button, parent) + return file_dialog("Enregistrer sous...", action, button, parent, ext) diff --git a/circuitbuilder/scriptingwrapper.py b/circuitbuilder/scriptingwrapper.py new file mode 100644 index 0000000..4679679 --- /dev/null +++ b/circuitbuilder/scriptingwrapper.py @@ -0,0 +1,20 @@ +from link import Link + +class ScriptingWrapper(object): + + builder_widget = None + component_factory = None + + def __init__(self, app): + self.builder_widget = app.builder_widget + self.component_factory = app.component_factory + + def add_link(self, output_gate, output_id, input_gate, input_id): + link = Link(output_gate, output_id, input_gate, input_id) + self.builder_widget.add_link_internal(link) + + def get_component(self, id): + try: + return self.component_factory.pool.components[id] + except KeyError: + return None diff --git a/circuitbuilder/scripts/link-base b/circuitbuilder/scripts/link-base new file mode 100644 index 0000000..4d23124 --- /dev/null +++ b/circuitbuilder/scripts/link-base @@ -0,0 +1,2 @@ +for i in range(components[0].outputs): + builder.add_link(components[0], i, components[1], i) diff --git a/circuitbuilder/undoredo.py b/circuitbuilder/undoredo.py index 5548fe3..4afbe3b 100644 --- a/circuitbuilder/undoredo.py +++ b/circuitbuilder/undoredo.py @@ -36,7 +36,7 @@ class UndoRedoAction(object): def redo(self, builder_widget): if self.__action == ACTION_ADD_GATE: - builder_widget.add_component(self.__component) + builder_widget.restore_component(self.__component) elif self.__action == ACTION_DEL_GATE: builder_widget.del_component(self.__component) elif self.__action == ACTION_ADD_LINK: diff --git a/circuitbuilder/viewer_widget.py b/circuitbuilder/viewer_widget.py index 4c52d45..2c1dfa8 100644 --- a/circuitbuilder/viewer_widget.py +++ b/circuitbuilder/viewer_widget.py @@ -26,16 +26,22 @@ pygtk.require ('2.0') import gtk import cairo +import pango import pangocairo import math from math import pi +import components + from constants import * +FONT_DESC = pango.FontDescription("Monospace 10") + def prepare_text(cr, text): pcr = pangocairo.CairoContext(cr) layout = pcr.create_layout() + layout.set_font_description(FONT_DESC) layout.set_text(text) return pcr, layout @@ -125,8 +131,7 @@ class CircuitViewerWidget(gtk.DrawingArea): end = link.input_gate link_square = self._get_link_square(start, end) self._links_squares[link] = link_square - self._redraw_surface() - self.queue_draw() + self.redraw_surface() def _get_components(self): return self._components @@ -186,21 +191,21 @@ class CircuitViewerWidget(gtk.DrawingArea): height = property(_get_height, _set_height) - def __update_component_surface(self): - cr = cairo.Context(self._component_surface) + def _make_component_surface(self, surface, component_type): + cr = cairo.Context(surface) cr.set_operator(cairo.OPERATOR_CLEAR) cr.paint() cr.set_operator(cairo.OPERATOR_OVER) cr.arc(PART_SIZE / 2, PART_SIZE / 2, (PART_SIZE / 2) - 1, 0, 2 * pi) cr.stroke() cr.set_source_rgb(0, 0, 0) - text = self._component_type.symbol - if hasattr(self._component_type, "input_id"): - input_id = self._component_type.input_id + text = component_type.symbol + if isinstance(component_type, components.Input): + input_id = component_type.input_id if input_id > 0: text = "%s %d" % (text, input_id) - if hasattr(self._component_type, "output_id"): - output_id = self._component_type.output_id + if isinstance(component_type, components.Output): + output_id = component_type.output_id if output_id > 0: text = "%s %d" % (text, output_id) pcr, layout = prepare_text(cr, text) @@ -211,6 +216,10 @@ class CircuitViewerWidget(gtk.DrawingArea): pcr.move_to(x0, y0) pcr.show_layout(layout) + def __update_component_surface(self): + self._make_component_surface(self._component_surface, + self._component_type) + def _set_component_type(self, component_type): if self._component_type != component_type: self._component_type = component_type diff --git a/circuitbuilder/xmlhandling.py b/circuitbuilder/xmlhandling.py index df5cbfd..a826c09 100644 --- a/circuitbuilder/xmlhandling.py +++ b/circuitbuilder/xmlhandling.py @@ -54,21 +54,23 @@ def parse_circuit(circuit, component_factory, id_prefix = None): components = {} components_list = [] for gate in circuit: + initial_data = {} gate_type = gate.tag id = gate.attrib["id"] - component = component_factory.create_component(gate_type) - if not component: - return None if id_prefix: id = id_prefix + id - component.id = id - component.x = int(gate.attrib["x"]) - component.y = int(gate.attrib["y"]) - component.inputs = int(gate.attrib["inputs"]) + initial_data["_id"] = id + initial_data["x"] = int(gate.attrib["x"]) + initial_data["y"] = int(gate.attrib["y"]) + initial_data["inputs"] = int(gate.attrib["inputs"]) if "input_id" in gate.attrib: - component.input_id = int(gate.attrib["input_id"]) + initial_data["_input_id"] = int(gate.attrib["input_id"]) if "output_id" in gate.attrib: - component.output_id = int(gate.attrib["output_id"]) + initial_data["_output_id"] = int(gate.attrib["output_id"]) + component = component_factory.create_component(gate_type, + initial_data) + if not component: + return None components[id] = component components_list.append(component) for gate in circuit: diff --git a/simul/Makefile b/simul/Makefile index d756157..1173a0c 100644 --- a/simul/Makefile +++ b/simul/Makefile @@ -1,8 +1,13 @@ -CMO=scheme.cmo compil.cmo reader.cmo main.cmo +CMO=scheme.cmo compil.cmo reader.cmo lexerPaths.cmo main.cmo CC=ocamlfind ocamlc -package libxml2 -linkpkg +LEX=ocamllex +GENERATED=lexerPaths.ml BIN=generator -.SUFFIXES: .ml .cmo .cmi +.SUFFIXES: .ml .mll .cmo .cmi + +.mll.ml: + $(LEX) $< .ml.cmo: $(CC) -c $< @@ -13,15 +18,15 @@ $(BIN): $(CMO) all: $(BIN) clean: - rm -f $(BIN) *.cm[io] .depend + rm -f $(GENERATED) $(BIN) *.cm[io] .depend test: $(BIN) ./generator FullAdder > test.cpp g++ -o test test.cpp ./test -.depend: +.depend: $(GENERATED) rm -f .depend ocamldep *.ml > .depend -include .depend +include .depend
\ No newline at end of file diff --git a/simul/compil.ml b/simul/compil.ml index bf23bb8..1826328 100644 --- a/simul/compil.ml +++ b/simul/compil.ml @@ -311,10 +311,6 @@ let triTopo gg = (*si on doit améliorer qqc, c'est ca*) génération de code ***************************************************************) -(******************id dans gates*************) -let cbTblId = Hashtbl.create 42 -let cbIdEC = ref 0 - (*********************classes utilisees**********) let cbTblCU = Hashtbl.create 17 @@ -350,6 +346,11 @@ let cbRegReg id idGate = let cbIdRegIToO s = (String.sub s 0 (String.length s - 2)) ^ "_o" +(********************ram/rom********************) +let cbLgrAdrRAM = 16 +let cbLgrAdrROM = 16 +let cbLgrMotRAM = 8 +let cbLgrMotROM = 8 (**************fonctions action*******************) let cbIdEntree = "Input" @@ -364,19 +365,22 @@ let cbIdNor = "Nor" let cbIdOr = "Or" let cbIdAnd = "And" let cbIdMux = "Mux" +let cbIdRAMW = "RAMW" +let cbIdRAMR = "RAMR" +let cbIdROMR = "ROMR" let cbTblFcts = Hashtbl.create 17 let cbTblFctsSpe = Hashtbl.create 17 let _ = Hashtbl.add cbTblFctsSpe cbIdSortie - "sortie = gates[parents[0]]->sortie;\ntabOutputs[idS] = sortie"; + "sortie = gates[parents[0]]->sortie;\ntabOutputs[idS] = sortie + 48"; Hashtbl.add cbTblFctsSpe cbIdEntree - "sortie = tabInputs[idE]"; + "sortie = (tabInputs[idE] - 48)"; Hashtbl.add cbTblFctsSpe cbIdNot "sortie = !(gates[parents[0]]->sortie)"; Hashtbl.add cbTblFctsSpe cbIdRegI - (Printf.sprintf "reinterpret_cast<%s>(gates[idO])->next = gates[parents[0]]->sortie" (cbIdRegO ^ "000*")); + (Printf.sprintf "reinterpret_cast<%s000*>(gates[idO])->next = gates[parents[0]]->sortie" cbIdRegO); Hashtbl.add cbTblFctsSpe cbIdRegO "sortie = next"; Hashtbl.add cbTblFctsSpe cbIdOne @@ -384,7 +388,26 @@ let _ = Hashtbl.add cbTblFctsSpe cbIdZero "sortie = false"; Hashtbl.add cbTblFctsSpe cbIdMux - "sortie = (gates[parents[0]]->sortie) ? gates[parents[2]]->sortie : gates[parents[1]]->sortie" + "sortie = (gates[parents[0]]->sortie) ? gates[parents[2]]->sortie : gates[parents[1]]->sortie"; + + let binToInt typemem ofs = + let str = ref "0" in + for i = 0 to (match typemem with |"RAM" -> cbLgrAdrRAM |"ROM" -> cbLgrAdrROM |_ -> failwith "mauvais type de mem") do + str := Printf.sprintf "%s+(gates[parents[%d]]->sortie << %d)" !str (i+ofs) i + done; + !str + in + for i = 0 to cbLgrMotRAM do + Hashtbl.add cbTblFctsSpe (Printf.sprintf "%s%d" cbIdRAMR i) + (Printf.sprintf "sortie = tabRAM[%s] & (1 << %d)" (binToInt "RAM" 0) i) + done; + for i = 0 to cbLgrMotRAM do + Hashtbl.add cbTblFctsSpe (Printf.sprintf "%s%d" cbIdROMR i) + (Printf.sprintf "sortie = tabROM[%s] & (1 << %d)" (binToInt "ROM" 0) i) + done; + Hashtbl.add cbTblFctsSpe cbIdRAMW + (Printf.sprintf "tabRAM[%s] = %s" (binToInt "RAM" 0) (binToInt "RAM" cbLgrAdrRAM)) + let cbConvertitOper = function @@ -436,8 +459,9 @@ struct gate { gate () :sortie(false) {}; }; -bool tabInputs[%d]; -bool tabOutputs[%d];\n\n" nEntrees nSorties +char tabInputs[%d]; +char tabOutputs[%d] = \"%s\"; +\n" (nEntrees + 1) (nSorties + 1) (String.make nSorties '0') (**************classes*********************) @@ -479,19 +503,20 @@ let cbClasses () = (***************portes*****************************) -let cbPortes g (mapentrees : int Smap.t) (mapsorties : int Smap.t) = - let cbRegPorte id = - Hashtbl.add cbTblId id (!cbIdEC); - incr cbIdEC - in - let cbGetPorteIdC id = - try - Hashtbl.find cbTblId id - with - |Not_found -> failwith "generation de code : id C non trouvee" - in +let cbPortes g (mapentrees : int Smap.t) (mapsorties : int Smap.t) nPortes = + let cbTblId = Hashtbl.create 42 in + let cbIdEC = ref (nPortes - 1) in + let cbGetIdGate id = + try + Hashtbl.find cbTblId id + with + |Not_found -> failwith (Printf.sprintf "cbPortes : id %s non trouvee" id) + in + let cbRegIdGate id = Hashtbl.add cbTblId id !cbIdEC; decr cbIdEC + in + let cbFormatePorte id kind parents = - cbRegPorte id; + cbRegIdGate id; (*ici les cas spéciaux*) try let k = cbGetKind kind in @@ -499,14 +524,14 @@ let cbPortes g (mapentrees : int Smap.t) (mapsorties : int Smap.t) = |a when a = cbIdEntree -> [string_of_int (Smap.find id mapentrees)] |a when a = cbIdSortie -> - (string_of_int (Smap.find id mapsorties))::(List.map (fun (i1, n1) -> string_of_int (cbGetPorteIdC i1)) parents) + (string_of_int (Smap.find id mapsorties))::(List.map (fun (i1, n1) -> string_of_int (cbGetIdGate i1)) parents) |a when a = cbIdRegO -> - cbRegReg id (!cbIdEC - 1); - List.map (fun (i1, n1) -> string_of_int (cbGetPorteIdC i1)) parents + cbRegReg id (!cbIdEC + 1); + List.map (fun (i1, n1) -> string_of_int (cbGetIdGate i1)) parents |a when a = cbIdRegI -> - (string_of_int (Hashtbl.find cbTblRegs (cbIdRegIToO id)))::(List.map (fun (i1, n1) -> string_of_int (cbGetPorteIdC i1)) parents) + (string_of_int (Hashtbl.find cbTblRegs (cbIdRegIToO id)))::(List.map (fun (i1, n1) -> string_of_int (cbGetIdGate i1)) parents) |_ -> - List.map (fun (i1, n1) -> string_of_int (cbGetPorteIdC i1)) parents + List.map (fun (i1, n1) -> string_of_int (cbGetIdGate i1)) parents ) in kind ^ " " ^ id ^ (if args = [] then "" else "(" ^ (cbFormateArgs args) ^ ")") ^ ";\n" @@ -519,7 +544,7 @@ let cbPortes g (mapentrees : int Smap.t) (mapsorties : int Smap.t) = (***********************tab************************) let cbTab g = - let tab = (List.fold_left (fun l (i, k) -> l ^ "&" ^ i ^ ", ") "{" g.sommets) ^ "}" in + let tab = (List.fold_left (fun l (i, k) -> l ^ "&" ^ i ^ ", ") "{" (List.rev g.sommets)) ^ "}" in Printf.printf "gate* gates[] = %s;\n" tab @@ -537,18 +562,13 @@ let cbActions () = let cbMain nPortes nEntrees nSorties = Printf.printf "int main () { - char temp[%d]; while(true) { - scanf(\"%%s\", temp); - for (int i = 0; i < %d; i++) - tabInputs[i] = temp[i] - 48; - for (int i = 0; i < %d; i++) + scanf(\"%%s\", tabInputs); + for (int i = %d - 1; i >= 0; i--) gates[i]->action(); - for (int i = 0; i < %d; i++) - printf(\"%%d\", tabOutputs[i]); - printf(\"\\n\"); + puts(tabOutputs); }; -}" (nEntrees+2) nEntrees nPortes nSorties +}" nPortes (**********************genere code****************) @@ -564,7 +584,7 @@ let cbGenereCode g (mapentrees : int Smap.t) (mapsorties : int Smap.t) = cbRegCU g; cbDebut nentrees nsorties; cbClasses (); - cbPortes g mapentrees mapsorties; + cbPortes g mapentrees mapsorties (List.length g.sommets); cbTab g; cbActions (); cbMain (List.length g.sommets) nentrees nsorties diff --git a/simul/fulladder.xnl b/simul/fulladder.xnl deleted file mode 100644 index c39292d..0000000 --- a/simul/fulladder.xnl +++ /dev/null @@ -1,33 +0,0 @@ -<circuit inputs="3" name="FullAdder" outputs="2" symbol="fa" min_height="268" min_width="457"> - <Input y="164" inputs="0" input_id="3" id="inC" x="28"> - <outputlink output_id="1" input_gate="xorB" input_id="2"/> - <outputlink output_id="1" input_gate="andA" input_id="2"/> - </Input> - <And y="228" inputs="2" id="andB" x="267"> - <outputlink output_id="1" input_gate="orA" input_id="2"/> - </And> - <Or y="189" inputs="2" id="orA" x="337"> - <outputlink output_id="1" input_gate="Cout" input_id="1"/> - </Or> - <Input y="63" inputs="0" input_id="1" id="inA" x="29"> - <outputlink output_id="1" input_gate="xorA" input_id="1"/> - <outputlink output_id="1" input_gate="andB" input_id="1"/> - </Input> - <Output y="119" inputs="1" output_id="1" id="S" x="415"/> - <Output y="220" inputs="1" output_id="2" id="Cout" x="417"/> - <Xor y="85" inputs="2" id="xorA" x="139"> - <outputlink output_id="1" input_gate="xorB" input_id="1"/> - <outputlink output_id="1" input_gate="andA" input_id="1"/> - </Xor> - <Input y="114" inputs="0" input_id="2" id="inB" x="29"> - <outputlink output_id="1" input_gate="xorA" input_id="2"/> - <outputlink output_id="1" input_gate="andB" input_id="2"/> - </Input> - <Xor y="119" inputs="2" id="xorB" x="249"> - <outputlink output_id="1" input_gate="S" input_id="1"/> - </Xor> - <And y="173" inputs="2" id="andA" x="267"> - <outputlink output_id="1" input_gate="orA" input_id="1"/> - </And> -</circuit> - diff --git a/simul/lexerPaths.ml b/simul/lexerPaths.ml new file mode 100644 index 0000000..cde4366 --- /dev/null +++ b/simul/lexerPaths.ml @@ -0,0 +1,127 @@ +# 1 "lexerPaths.mll" + + let tblPaths = Hashtbl.create 17 + +# 6 "lexerPaths.ml" +let __ocaml_lex_tables = { + Lexing.lex_base = + "\000\000\253\255\001\000\002\000"; + Lexing.lex_backtrk = + "\001\000\255\255\001\000\000\000"; + Lexing.lex_default = + "\002\000\000\000\002\000\255\255"; + Lexing.lex_trans = + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\003\000\255\255\003\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ + \001\000\255\255\000\000"; + Lexing.lex_check = + "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\000\000\002\000\003\000\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\ + \000\000\002\000\255\255"; + Lexing.lex_base_code = + ""; + Lexing.lex_backtrk_code = + ""; + Lexing.lex_default_code = + ""; + Lexing.lex_trans_code = + ""; + Lexing.lex_check_code = + ""; + Lexing.lex_code = + ""; +} + +let rec readWord lexbuf = + __ocaml_lex_readWord_rec lexbuf 0 +and __ocaml_lex_readWord_rec lexbuf __ocaml_lex_state = + match Lexing.engine __ocaml_lex_tables __ocaml_lex_state lexbuf with + | 0 -> +# 9 "lexerPaths.mll" + (readWord lexbuf) +# 103 "lexerPaths.ml" + + | 1 -> +let +# 10 "lexerPaths.mll" + word +# 109 "lexerPaths.ml" += Lexing.sub_lexeme lexbuf lexbuf.Lexing.lex_start_pos lexbuf.Lexing.lex_curr_pos in +# 10 "lexerPaths.mll" + (Hashtbl.add tblPaths word (); readWord lexbuf) +# 113 "lexerPaths.ml" + + | 2 -> +# 11 "lexerPaths.mll" + ( () ) +# 118 "lexerPaths.ml" + + | __ocaml_lex_state -> lexbuf.Lexing.refill_buff lexbuf; __ocaml_lex_readWord_rec lexbuf __ocaml_lex_state + +;; + +# 15 "lexerPaths.mll" + + let read ch = Hashtbl.clear tblPaths; readWord (Lexing.from_channel ch); tblPaths + +# 128 "lexerPaths.ml" diff --git a/simul/lexerPaths.mll b/simul/lexerPaths.mll new file mode 100644 index 0000000..ce8b605 --- /dev/null +++ b/simul/lexerPaths.mll @@ -0,0 +1,17 @@ +{ + let tblPaths = Hashtbl.create 17 +} + +(*let letter = ['a'-'z' 'A'-'Z' '0'-'9' '.' '/' '#' '~']*) +let blank = [' ' '\t' '\n'] + +rule readWord = parse + |'\n'+ {readWord lexbuf} + |[^ '\n']* as word {Hashtbl.add tblPaths word (); readWord lexbuf} + |eof { () } + + + +{ + let read ch = Hashtbl.clear tblPaths; readWord (Lexing.from_channel ch); tblPaths +} diff --git a/simul/main.ml b/simul/main.ml index 42a2e6f..f35823b 100644 --- a/simul/main.ml +++ b/simul/main.ml @@ -1,5 +1,7 @@ open Scheme +let pathfilename = "paths" + let estXNL a = if (String.length a < 4) then false @@ -19,16 +21,27 @@ let printsimap s = Printf.printf "\n" let _ = - let files = Sys.readdir "." in + let pathfile = open_in pathfilename in + let paths = LexerPaths.read pathfile in + + Hashtbl.iter (fun path _ -> Printf.fprintf stderr "%s\n" path; + let files = Sys.readdir path in for i = 0 to Array.length files - 1 do - if estXNL files.(i) then - Compil.regCircuit (Reader.parse_file files.(i)) - done; - let schMain = Compil.findSchema (Sys.argv.(1) ^ "XXX") in - let schMain2 = delesscheme schMain in - let t = Compil.triTopo (Compil.completeGraphe - schMain2 "" - Imap.empty - Imap.empty) in - Compil.cbGenereCode t (simap_to_ismap schMain.entrees) (simap_to_ismap schMain.sorties) + if estXNL files.(i) then begin + Compil.regCircuit (Reader.parse_file (path ^ files.(i))); + Printf.fprintf stderr "Circuit ouvert : %s\n" (path ^ files.(i)) + end + done + ) paths; + let schMain = Compil.findSchema (Sys.argv.(1) ^ "XXX") in + let schMain2 = delesscheme schMain in + Printf.fprintf stderr "Compilation : %f\n" (Sys.time()); + let t = Compil.completeGraphe + schMain2 "" + Imap.empty + Imap.empty in + Printf.fprintf stderr "Tritopo %f\n" (Sys.time()); + let t = Compil.triTopo t in + Printf.fprintf stderr "Fin %f\n" (Sys.time()); + Compil.cbGenereCode t (simap_to_ismap schMain.entrees) (simap_to_ismap schMain.sorties) diff --git a/simul/maketest b/simul/maketest index 2c600fc..94bf024 100755 --- a/simul/maketest +++ b/simul/maketest @@ -1,2 +1,7 @@ #!/bin/bash -echo "Generating & compiling C++ source" && cp ../components/*.xnl . && ./generator $1 > $1.cpp && g++ -o $1 $1.cpp && echo "Testing..." && ./$1 +echo "Generating & compiling C++ source" && +make && +./generator $1 > $1.cpp && +g++ -O5 -o $1 $1.cpp && +echo "Testing..." && +./$1 diff --git a/simul/paths b/simul/paths new file mode 100644 index 0000000..cda7dcf --- /dev/null +++ b/simul/paths @@ -0,0 +1,2 @@ +. +../components/
\ No newline at end of file diff --git a/utils/tick.c b/utils/tick.c index 2b6c91d..223f131 100755 --- a/utils/tick.c +++ b/utils/tick.c @@ -7,12 +7,20 @@ int main(int argc, char **argv) { struct timeval time; struct timespec req; - int last_sec = 0; - int nsecs = 1000000000 / atoi(argv[1]); + gettimeofday(&time, NULL); + long int last_usec = time.tv_usec; + long int usecs_delta; + unsigned int max_usecs = 1000000 / atoi(argv[1]); req.tv_sec = 0; for (;;) { - req.tv_nsec = nsecs; + gettimeofday(&time, NULL); + //printf("%d %d\n", usecs_delta, req.tv_nsec); + usecs_delta = time.tv_usec - last_usec; + if (usecs_delta < 0) + usecs_delta = time.tv_usec - last_usec + 1000000; + req.tv_nsec = (2 * max_usecs - usecs_delta) * 1000; + last_usec = time.tv_usec; nanosleep(&req, NULL); printf("1\n"); fflush(stdout); diff --git a/utils/tick.cpp b/utils/tick.cpp new file mode 100644 index 0000000..6155bfd --- /dev/null +++ b/utils/tick.cpp @@ -0,0 +1,60 @@ +#include <stdio.h> +#include <unistd.h> +#include <time.h> +#include <stdlib.h> +#include <sys/time.h> + +struct timeC { + int u; + long s; + timeC operator + (const timeC & a) { + timeC ret; + ret.u = u + a.u; + ret.s = s + a.s; + if (ret.u > 1000000) { + ret.u -= 1000000; + ret.s++; + }; + return ret; + }; + timeC operator - (const timeC & a) { + timeC ret; + ret.u = u - a.u; + ret.s = s - a.s; + if (ret.u < 0) { + ret.u += 1000000; + ret.s--; + }; + return ret; + }; + timeC () + :u(0), s(0) {}; + timeC (const timeval & t) + :u(t.tv_usec), s(t.tv_sec) {}; + operator timespec () const { + timespec ret; + ret.tv_sec = s; + ret.tv_nsec = u * 1000; + return ret; + }; +}; + +int main(int argc, char **argv) +{ + struct timeval time; + struct timespec req; + gettimeofday(&time, NULL); + timeC max_nsecs; + max_nsecs.u = 1000000 / atoi(argv[1]); + timeC next = max_nsecs + time; + for (;;) + { + gettimeofday(&time, NULL); + req = next - time; + next = next + max_nsecs; + nanosleep(&req, NULL); + printf("1\n"); + fflush(stdout); + } + return 0; +} |