--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="src" path="test/src"/>\r
+ <classpathentry kind="lib" path="jars/jdom.jar"/>\r
+ <classpathentry kind="lib" path="jars/xercesImpl.jar"/>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>DOL_tecmp</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="dol" default="compile" basedir=".">
+
+ <description>
+ Ant build file for DOL and its documentation.
+ </description>
+
+ <!-- ************************************************************** -->
+ <!-- properties -->
+ <!-- ************************************************************** -->
+ <!-- source directories -->
+ <property name="dol.path" value="${basedir}"/>
+ <property name="systemc.inc" value="/home/shapes/base/resources/lib/systemC/include"/>
+ <property name="systemc.lib" value="/home/shapes/base/resources/lib/systemC/lib-linux/libsystemc.a"/>
+
+ <property name="src.dir" location="src"/>
+ <property name="doc.dir" location="docs"/>
+ <property name="jars.dir" location="jars"/>
+ <property name="example.dir" location="examples"/>
+
+ <!-- build directories -->
+ <property name="build.dir" location="build"/>
+ <property name="bin.dir" location="${build.dir}/bin"/>
+ <property name="bin.main.dir" location="${bin.dir}/main"/>
+ <property name="doc.api.dir" location="${doc.dir}/api"/>
+ <property name="doc.build.dir" location="${build.dir}/docs"/>
+ <property name="expo.dir" location="../expo"/>
+
+ <!-- distribution directories -->
+ <property name="bin-dist.name" value="dol.jar"/>
+ <property name="api.name" value="SHAPES Distributed Operation Layer (DOL)"/>
+
+ <!-- jar files -->
+ <property name="jars" value=".:${jars.dir}/jdom.jar:${jars.dir}/xercesImpl.jar"/>
+
+
+ <!-- *************************************************************** -->
+ <!-- tasks -->
+ <!-- *************************************************************** -->
+ <!-- build all -->
+ <target name="all" depends="config, compile"/>
+
+ <!-- compile DOL java classes -->
+ <target name="compile">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${bin.dir}"/>
+ <mkdir dir="${bin.main.dir}"/>
+
+ <!-- compile dol sources -->
+ <javac destdir="${bin.main.dir}" debug="true" classpath="${jars}">
+ <src path="${src.dir}"/>
+ <compilerarg value="-Xlint:unchecked"/>
+ </javac>
+ <javac destdir="${bin.main.dir}"
+ debug="true"
+ classpath="jars/jdom.jar:jars/xercesImpl.jar">
+ <src path="test/src"/>
+ </javac>
+ <copy todir="${bin.main.dir}" file="${src.dir}/dol.properties"/>
+ <copy todir="${bin.main.dir}">
+ <fileset dir="${src.dir}"
+ includes="dol/visitor/systemC/lib/**
+ dol/visitor/hds/lib/**
+ dol/visitor/PipeAndFilter/lib/**
+ dol/visitor/hdsd/lib/**
+ dol/visitor/hdsd/scd/**
+ dol/visitor/hdsd/scd/fsm/**
+ dol/visitor/rtems/lib/**
+ dol/visitor/protothread/lib/**
+ dol/visitor/cbe/lib/**
+ dol/visitor/cbe/template/**
+ dol/visitor/cell/lib/**
+ dol/visitor/cell/template/**"/>
+ </copy>
+
+ <!-- copy example run scripts -->
+ <copy todir="${bin.main.dir}" file="examples/runexample.xml"/>
+ <copy todir="${bin.main.dir}" file="examples/runprofiler.xml"/>
+ <copy todir="${bin.main.dir}">
+ <fileset dir="examples"
+ includes="schema/**"
+ excludes="schema/createschemastex"/>
+ </copy>
+
+ <!-- compile test sources -->
+ <javac destdir="${bin.main.dir}"
+ debug="true"
+ classpath="jars/jdom.jar:jars/xercesImpl.jar">
+ <src path="test/src"/>
+ </javac>
+ <copy todir="${bin.main.dir}" file="test/runtests.xml"/>
+ <copy tofile="${bin.main.dir}/test.properties" file="test/test.properties">
+ <filterchain>
+ <replacetokens>
+ <token key="schema_path" value="${example.dir}/schema"/>
+ </replacetokens>
+ </filterchain>
+ <filterchain>
+ <tokenfilter>
+ <replaceregex pattern="(.)\\([^ ])"
+ replace="\1/\2"
+ flags="g"/>
+ </tokenfilter>
+ </filterchain>
+ </copy>
+
+ <antcall target="createjar"/>
+ <!-- <antcall target="javadoc"/> -->
+ </target>
+
+ <target name="config">
+ <echo message="Create new dol.properties file."/>
+ <delete file="${src.dir}/dol.properties" quiet="true"/>
+ <copy file="${src.dir}/dol_template.properties"
+ tofile="${src.dir}/dol.properties">
+ <filterchain>
+ <replacetokens>
+ <token key="dol_path" value="${dol.path}"/>
+ <token key="systemc_inc" value="${systemc.inc}"/>
+ <token key="systemc_lib" value="${systemc.lib}"/>
+ </replacetokens>
+ </filterchain>
+ </copy>
+ </target>
+
+ <!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ <target name="test" depends="compile">
+ <javac destdir="${bin.main.dir}" debug="true" classpath="jars/jdom.jar:jar/xercesImpl.jar">
+ <src path="test/src"/>
+ </javac>
+ <copy todir="${bin.main.dir}" file="test/runtests.xml"/>
+ <copy todir="${bin.main.dir}" file="examples/runexample.xml"/>
+ <copy tofile="${bin.main.dir}/test.properties" file="test/test.properties">
+ <filterchain>
+ <replacetokens>
+ <token key="schema_path" value="${example.dir}/schema"/>
+ </replacetokens>
+ </filterchain>
+ <filterchain>
+ <tokenfilter>
+ <replaceregex pattern="(.)\\([^ ])"
+ replace="\1/\2"
+ flags="g"/>
+ </tokenfilter>
+ </filterchain>
+ </copy>
+ </target>
+ -->
+
+ <target name="javadoc">
+ <mkdir dir="${doc.build.dir}"/>
+ <javadoc packagenames="dol.*"
+ classpath="${jars}"
+ sourcepath="${src.dir}"
+ destdir="${doc.build.dir}"
+ access="public"
+ author="true"
+ version="true"
+ use="true"
+ windowtitle="${api.name}">
+ <doctitle><![CDATA[<h1>${api.name}</h1>]]></doctitle>
+ <bottom><![CDATA[<i>Copyright © 2005-2007 Computer Engineering and Networks Laboratory (TIK), ETH Zürich. All Rights Reserved.</i>]]></bottom>
+ </javadoc>
+ </target>
+
+ <target name="createjar">
+ <jar destfile="${bin-dist.name}" manifest="${src.dir}/MANIFEST.MF">
+ <fileset dir="${bin.main.dir}"
+ includes="dol/** dol.properties"/>
+ <fileset dir="examples"
+ includes="schema/**"
+ excludes="schema/createschemastex"/>
+ </jar>
+ <copy file="${bin-dist.name}" todir="${expo.dir}/jars"/>
+ </target>
+
+ <!-- clean up everything -->
+ <target name="clean">
+ <delete dir="${build.dir}"/>
+ <delete file="${bin-dist.name}"/>
+ </target>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<architecture xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE
+ http://www.tik.ee.ethz.ch/~shapes/schema/architecture.xsd"
+ name="Sony/Toshiba/IBM Cell Broadband Engine architecture">
+
+ <processor name="ppu" type="RISC">
+ </processor>
+
+ <processor name="spu_0" type="DSP">
+ </processor>
+
+ <processor name="spu_1" type="DSP">
+ </processor>
+
+ <processor name="spu_2" type="DSP">
+ </processor>
+
+ <processor name="spu_3" type="DSP">
+ </processor>
+
+ <processor name="spu_4" type="DSP">
+ </processor>
+
+ <processor name="spu_5" type="DSP">
+ </processor>
+
+</architecture>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<architecture xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE
+ http://www.tik.ee.ethz.ch/~shapes/schema/architecture.xsd"
+ name="MPARM architecture">
+
+ <processor name="processor_0" basename="processor" range="8" type="RISC">
+ </processor>
+
+ <processor name="processor_1" basename="processor" range="8" type="RISC">
+ </processor>
+
+ <processor name="processor_2" basename="processor" range="8" type="RISC">
+ </processor>
+
+ <processor name="processor_3" basename="processor" range="8" type="RISC">
+ </processor>
+
+ <processor name="processor_4" basename="processor" range="8" type="RISC">
+ </processor>
+
+ <processor name="processor_5" basename="processor" range="8" type="RISC">
+ </processor>
+
+ <processor name="processor_6" basename="processor" range="8" type="RISC">
+ </processor>
+
+ <processor name="processor_7" basename="processor" range="8" type="RISC">
+ </processor>
+</architecture>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<architecture xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE\r
+ http://www.tik.ee.ethz.ch/~shapes/schema/architecture.xsd"\r
+ name="RDT1">\r
+\r
+ <!-- rdt(tile_0) arm subsystem -->\r
+ <processor name="tile_0.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_0.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_0.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!-- rdt(tile_0) magic subsystem -->\r
+ <processor name="tile_0.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_0.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_0.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_0.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!-- rdt(tile_0) distributed external memory -->\r
+ <memory name="tile_0.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <!-- rdt(tile_0) ahb multi-layer bus -->\r
+ <hw_channel name="tile_0.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_0.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!-- rdt(tile_0) dnp -->\r
+ <hw_channel name="tile_0.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!-- rdt(tile_0) on-tile communication paths -->\r
+ <!-- rdt(tile_0) arm paths via dxm-->\r
+ <writepath name="tile_0.rdmtodxm">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.armbus"/>\r
+ <hw_channel name="tile_0.ahb1"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_0.rdmfromdxm">\r
+ <processor name="tile_0.arm"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ <hw_channel name="tile_0.ahb1"/>\r
+ <hw_channel name="tile_0.armbus"/>\r
+ <rxbuf name="tile_0.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- rdt(tile_0) arm paths via rdm-->\r
+ <writepath name="tile_0.rdmtordm">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.armbus"/>\r
+ <chbuf name="tile_0.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_0.rdmfromrdm">\r
+ <processor name="tile_0.arm"/>\r
+ <chbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.armbus"/>\r
+ <rxbuf name="tile_0.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- rdt(tile_0) magic paths via ddm-->\r
+ <writepath name="tile_0.ddmtoddm">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.magicbus"/>\r
+ <chbuf name="tile_0.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_0.ddmfromddm">\r
+ <processor name="tile_0.magic"/>\r
+ <chbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.magicbus"/>\r
+ <rxbuf name="tile_0.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- rdt(tile_0) magic paths via dxm-->\r
+ <writepath name="tile_0.ddmtodxm">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.dma"/>\r
+ <hw_channel name="tile_0.ahb1"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_0.ddmfromdxm">\r
+ <processor name="tile_0.magic"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ <hw_channel name="tile_0.ahb1"/>\r
+ <hw_channel name="tile_0.dma"/>\r
+ <rxbuf name="tile_0.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+</architecture>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<architecture xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE\r
+ http://www.tik.ee.ethz.ch/~shapes/schema/architecture.xsd"\r
+ name="RDT8">\r
+ <!-- 8 Tiles communicating via a mesh of DNPs -->\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_0 -->\r
+ <!--*****************************************************************-->\r
+ <processor name="tile_0.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_0.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_0.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <processor name="tile_0.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_0.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_0.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_0.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <memory name="tile_0.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_0.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_0.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_0.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_1 -->\r
+ <!--*****************************************************************-->\r
+ <processor name="tile_1.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_1.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_1.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <processor name="tile_1.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_1.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_1.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_1.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <memory name="tile_1.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_1.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_1.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_1.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_2 -->\r
+ <!--*****************************************************************-->\r
+ <processor name="tile_2.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_2.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_2.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <processor name="tile_2.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_2.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_2.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_2.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <memory name="tile_2.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_2.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_2.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_2.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_3 -->\r
+ <!--*****************************************************************-->\r
+ <processor name="tile_3.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_3.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_3.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <processor name="tile_3.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_3.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_3.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_3.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <memory name="tile_3.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_3.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_3.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_3.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_4 -->\r
+ <!--*****************************************************************-->\r
+ <processor name="tile_4.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_4.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_4.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <processor name="tile_4.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_4.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_4.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_4.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <memory name="tile_4.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_4.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_4.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_4.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_5 -->\r
+ <!--*****************************************************************-->\r
+ <processor name="tile_5.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_5.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_5.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <processor name="tile_5.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_5.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_5.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_5.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <memory name="tile_5.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_5.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_5.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_5.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_6 -->\r
+ <!--*****************************************************************-->\r
+ <processor name="tile_6.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_6.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_6.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <processor name="tile_6.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_6.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_6.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_6.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <memory name="tile_6.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_6.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_6.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_6.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_7 -->\r
+ <!--*****************************************************************-->\r
+ <processor name="tile_7.arm" type="RISC">\r
+ </processor>\r
+\r
+ <memory name="tile_7.rdm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_7.armbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <processor name="tile_7.magic" type="DSP">\r
+ </processor>\r
+\r
+ <memory name="tile_7.ddm" type="RAM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_7.magicbus" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_7.dma" type="DMA">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <memory name="tile_7.dxm" type="DXM">\r
+ </memory>\r
+\r
+ <hw_channel name="tile_7.ahb0" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_7.ahb1" type="BUS">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+ <hw_channel name="tile_7.dnp" type="SPI">\r
+ <configuration name="frequency" value="100000000"/>\r
+ <configuration name="bytespercycle" value="1"/>\r
+ </hw_channel>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_0 communication paths -->\r
+ <!--*****************************************************************-->\r
+ <writepath name="tile_0.rdmtodxm">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.armbus"/>\r
+ <hw_channel name="tile_0.ahb1"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_0.rdmfromdxm">\r
+ <processor name="tile_0.arm"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ <hw_channel name="tile_0.ahb1"/>\r
+ <hw_channel name="tile_0.armbus"/>\r
+ <rxbuf name="tile_0.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_0.rdmtordm">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.armbus"/>\r
+ <chbuf name="tile_0.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_0.rdmfromrdm">\r
+ <processor name="tile_0.arm"/>\r
+ <chbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.armbus"/>\r
+ <rxbuf name="tile_0.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_0.ddmtoddm">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.magicbus"/>\r
+ <chbuf name="tile_0.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_0.ddmfromddm">\r
+ <processor name="tile_0.magic"/>\r
+ <chbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.magicbus"/>\r
+ <rxbuf name="tile_0.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_0.ddmtodxm">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.dma"/>\r
+ <hw_channel name="tile_0.ahb1"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_0.ddmfromdxm">\r
+ <processor name="tile_0.magic"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ <hw_channel name="tile_0.ahb1"/>\r
+ <hw_channel name="tile_0.dma"/>\r
+ <rxbuf name="tile_0.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- tile_0 ARM inter-tile communication paths -->\r
+ <writepath name="tile_0.rdmtodnp_1">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.rdmtodnp_2">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.rdmtodnp_3">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.rdmtodnp_4">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.rdmtodnp_5">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.rdmtodnp_6">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.rdmtodnp_7">\r
+ <processor name="tile_0.arm"/>\r
+ <txbuf name="tile_0.rdm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+ <!-- tile_0 DSP inter-tile communication paths -->\r
+ <writepath name="tile_0.ddmtodnp_1">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.ddmtodnp_2">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.ddmtodnp_3">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.ddmtodnp_4">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.ddmtodnp_5">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.ddmtodnp_6">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_0.ddmtodnp_7">\r
+ <processor name="tile_0.magic"/>\r
+ <txbuf name="tile_0.ddm"/>\r
+ <hw_channel name="tile_0.ahb0"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_1 communication paths -->\r
+ <!--*****************************************************************-->\r
+ <writepath name="tile_1.rdmtodxm">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.armbus"/>\r
+ <hw_channel name="tile_1.ahb1"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_1.rdmfromdxm">\r
+ <processor name="tile_1.arm"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ <hw_channel name="tile_1.ahb1"/>\r
+ <hw_channel name="tile_1.armbus"/>\r
+ <rxbuf name="tile_1.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_1.rdmtordm">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.armbus"/>\r
+ <chbuf name="tile_1.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_1.rdmfromrdm">\r
+ <processor name="tile_1.arm"/>\r
+ <chbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.armbus"/>\r
+ <rxbuf name="tile_1.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_1.ddmtoddm">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.magicbus"/>\r
+ <chbuf name="tile_1.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_1.ddmfromddm">\r
+ <processor name="tile_1.magic"/>\r
+ <chbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.magicbus"/>\r
+ <rxbuf name="tile_1.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_1.ddmtodxm">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.dma"/>\r
+ <hw_channel name="tile_1.ahb1"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_1.ddmfromdxm">\r
+ <processor name="tile_1.magic"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ <hw_channel name="tile_1.ahb1"/>\r
+ <hw_channel name="tile_1.dma"/>\r
+ <rxbuf name="tile_1.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- tile_1 ARM inter-tile communication paths -->\r
+ <writepath name="tile_1.rdmtodnp_0">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.rdmtodnp_2">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.rdmtodnp_3">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.rdmtodnp_4">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.rdmtodnp_5">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.rdmtodnp_6">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.rdmtodnp_7">\r
+ <processor name="tile_1.arm"/>\r
+ <txbuf name="tile_1.rdm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+ <!-- tile_1 DSP inter-tile communication paths -->\r
+ <writepath name="tile_1.ddmtodnp_0">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.ddmtodnp_2">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.ddmtodnp_3">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.ddmtodnp_4">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.ddmtodnp_5">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.ddmtodnp_6">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_1.ddmtodnp_7">\r
+ <processor name="tile_1.magic"/>\r
+ <txbuf name="tile_1.ddm"/>\r
+ <hw_channel name="tile_1.ahb0"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_2 communication paths -->\r
+ <!--*****************************************************************-->\r
+ <writepath name="tile_2.rdmtodxm">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.armbus"/>\r
+ <hw_channel name="tile_2.ahb1"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_2.rdmfromdxm">\r
+ <processor name="tile_2.arm"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ <hw_channel name="tile_2.ahb1"/>\r
+ <hw_channel name="tile_2.armbus"/>\r
+ <rxbuf name="tile_2.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_2.rdmtordm">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.armbus"/>\r
+ <chbuf name="tile_2.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_2.rdmfromrdm">\r
+ <processor name="tile_2.arm"/>\r
+ <chbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.armbus"/>\r
+ <rxbuf name="tile_2.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_2.ddmtoddm">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.magicbus"/>\r
+ <chbuf name="tile_2.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_2.ddmfromddm">\r
+ <processor name="tile_2.magic"/>\r
+ <chbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.magicbus"/>\r
+ <rxbuf name="tile_2.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_2.ddmtodxm">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.dma"/>\r
+ <hw_channel name="tile_2.ahb1"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_2.ddmfromdxm">\r
+ <processor name="tile_2.magic"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ <hw_channel name="tile_2.ahb1"/>\r
+ <hw_channel name="tile_2.dma"/>\r
+ <rxbuf name="tile_2.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- tile_2 ARM inter-tile communication paths -->\r
+ <writepath name="tile_2.rdmtodnp_0">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.rdmtodnp_1">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.rdmtodnp_3">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.rdmtodnp_4">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.rdmtodnp_5">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.rdmtodnp_6">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.rdmtodnp_7">\r
+ <processor name="tile_2.arm"/>\r
+ <txbuf name="tile_2.rdm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+ <!-- tile_2 DSP inter-tile communication paths -->\r
+ <writepath name="tile_2.ddmtodnp_0">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.ddmtodnp_1">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.ddmtodnp_3">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.ddmtodnp_4">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.ddmtodnp_5">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.ddmtodnp_6">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_2.ddmtodnp_7">\r
+ <processor name="tile_2.magic"/>\r
+ <txbuf name="tile_2.ddm"/>\r
+ <hw_channel name="tile_2.ahb0"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_3 communication paths -->\r
+ <!--*****************************************************************-->\r
+ <writepath name="tile_3.rdmtodxm">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.armbus"/>\r
+ <hw_channel name="tile_3.ahb1"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_3.rdmfromdxm">\r
+ <processor name="tile_3.arm"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ <hw_channel name="tile_3.ahb1"/>\r
+ <hw_channel name="tile_3.armbus"/>\r
+ <rxbuf name="tile_3.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_3.rdmtordm">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.armbus"/>\r
+ <chbuf name="tile_3.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_3.rdmfromrdm">\r
+ <processor name="tile_3.arm"/>\r
+ <chbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.armbus"/>\r
+ <rxbuf name="tile_3.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_3.ddmtoddm">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.magicbus"/>\r
+ <chbuf name="tile_3.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_3.ddmfromddm">\r
+ <processor name="tile_3.magic"/>\r
+ <chbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.magicbus"/>\r
+ <rxbuf name="tile_3.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_3.ddmtodxm">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.dma"/>\r
+ <hw_channel name="tile_3.ahb1"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_3.ddmfromdxm">\r
+ <processor name="tile_3.magic"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ <hw_channel name="tile_3.ahb1"/>\r
+ <hw_channel name="tile_3.dma"/>\r
+ <rxbuf name="tile_3.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- tile_3 ARM inter-tile communication paths -->\r
+ <writepath name="tile_3.rdmtodnp_0">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.rdmtodnp_1">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.rdmtodnp_2">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.rdmtodnp_4">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.rdmtodnp_5">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.rdmtodnp_6">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.rdmtodnp_7">\r
+ <processor name="tile_3.arm"/>\r
+ <txbuf name="tile_3.rdm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+ <!-- tile_3 DSP inter-tile communication paths -->\r
+ <writepath name="tile_3.ddmtodnp_0">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.ddmtodnp_1">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.ddmtodnp_2">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.ddmtodnp_4">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.ddmtodnp_5">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.ddmtodnp_6">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_3.ddmtodnp_7">\r
+ <processor name="tile_3.magic"/>\r
+ <txbuf name="tile_3.ddm"/>\r
+ <hw_channel name="tile_3.ahb0"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_4 communication paths -->\r
+ <!--*****************************************************************-->\r
+ <writepath name="tile_4.rdmtodxm">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.armbus"/>\r
+ <hw_channel name="tile_4.ahb1"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_4.rdmfromdxm">\r
+ <processor name="tile_4.arm"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ <hw_channel name="tile_4.ahb1"/>\r
+ <hw_channel name="tile_4.armbus"/>\r
+ <rxbuf name="tile_4.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_4.rdmtordm">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.armbus"/>\r
+ <chbuf name="tile_4.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_4.rdmfromrdm">\r
+ <processor name="tile_4.arm"/>\r
+ <chbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.armbus"/>\r
+ <rxbuf name="tile_4.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_4.ddmtoddm">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.magicbus"/>\r
+ <chbuf name="tile_4.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_4.ddmfromddm">\r
+ <processor name="tile_4.magic"/>\r
+ <chbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.magicbus"/>\r
+ <rxbuf name="tile_4.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_4.ddmtodxm">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.dma"/>\r
+ <hw_channel name="tile_4.ahb1"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_4.ddmfromdxm">\r
+ <processor name="tile_4.magic"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ <hw_channel name="tile_4.ahb1"/>\r
+ <hw_channel name="tile_4.dma"/>\r
+ <rxbuf name="tile_4.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- tile_4 ARM inter-tile communication paths -->\r
+ <writepath name="tile_4.rdmtodnp_0">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.rdmtodnp_1">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.rdmtodnp_2">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.rdmtodnp_3">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.rdmtodnp_5">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.rdmtodnp_6">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.rdmtodnp_7">\r
+ <processor name="tile_4.arm"/>\r
+ <txbuf name="tile_4.rdm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+ <!-- tile_4 DSP inter-tile communication paths -->\r
+ <writepath name="tile_4.ddmtodnp_0">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.ddmtodnp_1">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.ddmtodnp_2">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.ddmtodnp_3">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.ddmtodnp_5">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.ddmtodnp_6">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_4.ddmtodnp_7">\r
+ <processor name="tile_4.magic"/>\r
+ <txbuf name="tile_4.ddm"/>\r
+ <hw_channel name="tile_4.ahb0"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_5 communication paths -->\r
+ <!--*****************************************************************-->\r
+ <writepath name="tile_5.rdmtodxm">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.armbus"/>\r
+ <hw_channel name="tile_5.ahb1"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_5.rdmfromdxm">\r
+ <processor name="tile_5.arm"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ <hw_channel name="tile_5.ahb1"/>\r
+ <hw_channel name="tile_5.armbus"/>\r
+ <rxbuf name="tile_5.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_5.rdmtordm">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.armbus"/>\r
+ <chbuf name="tile_5.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_5.rdmfromrdm">\r
+ <processor name="tile_5.arm"/>\r
+ <chbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.armbus"/>\r
+ <rxbuf name="tile_5.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_5.ddmtoddm">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.magicbus"/>\r
+ <chbuf name="tile_5.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_5.ddmfromddm">\r
+ <processor name="tile_5.magic"/>\r
+ <chbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.magicbus"/>\r
+ <rxbuf name="tile_5.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_5.ddmtodxm">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.dma"/>\r
+ <hw_channel name="tile_5.ahb1"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_5.ddmfromdxm">\r
+ <processor name="tile_5.magic"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ <hw_channel name="tile_5.ahb1"/>\r
+ <hw_channel name="tile_5.dma"/>\r
+ <rxbuf name="tile_5.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- tile_5 ARM inter-tile communication paths -->\r
+ <writepath name="tile_5.rdmtodnp_0">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.rdmtodnp_1">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.rdmtodnp_2">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.rdmtodnp_3">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.rdmtodnp_4">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.rdmtodnp_6">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.rdmtodnp_7">\r
+ <processor name="tile_5.arm"/>\r
+ <txbuf name="tile_5.rdm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+ <!-- tile_5 DSP inter-tile communication paths -->\r
+ <writepath name="tile_5.ddmtodnp_0">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.ddmtodnp_1">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.ddmtodnp_2">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.ddmtodnp_3">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.ddmtodnp_4">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.ddmtodnp_6">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_5.ddmtodnp_7">\r
+ <processor name="tile_5.magic"/>\r
+ <txbuf name="tile_5.ddm"/>\r
+ <hw_channel name="tile_5.ahb0"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_6 communication paths -->\r
+ <!--*****************************************************************-->\r
+ <writepath name="tile_6.rdmtodxm">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.armbus"/>\r
+ <hw_channel name="tile_6.ahb1"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_6.rdmfromdxm">\r
+ <processor name="tile_6.arm"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ <hw_channel name="tile_6.ahb1"/>\r
+ <hw_channel name="tile_6.armbus"/>\r
+ <rxbuf name="tile_6.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_6.rdmtordm">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.armbus"/>\r
+ <chbuf name="tile_6.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_6.rdmfromrdm">\r
+ <processor name="tile_6.arm"/>\r
+ <chbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.armbus"/>\r
+ <rxbuf name="tile_6.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_6.ddmtoddm">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.magicbus"/>\r
+ <chbuf name="tile_6.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_6.ddmfromddm">\r
+ <processor name="tile_6.magic"/>\r
+ <chbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.magicbus"/>\r
+ <rxbuf name="tile_6.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_6.ddmtodxm">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.dma"/>\r
+ <hw_channel name="tile_6.ahb1"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_6.ddmfromdxm">\r
+ <processor name="tile_6.magic"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ <hw_channel name="tile_6.ahb1"/>\r
+ <hw_channel name="tile_6.dma"/>\r
+ <rxbuf name="tile_6.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- tile_6 ARM inter-tile communication paths -->\r
+ <writepath name="tile_6.rdmtodnp_0">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.rdmtodnp_1">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.rdmtodnp_2">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.rdmtodnp_3">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.rdmtodnp_4">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.rdmtodnp_5">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.rdmtodnp_7">\r
+ <processor name="tile_6.arm"/>\r
+ <txbuf name="tile_6.rdm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+ <!-- tile_6 DSP inter-tile communication paths -->\r
+ <writepath name="tile_6.ddmtodnp_0">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.ddmtodnp_1">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.ddmtodnp_2">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.ddmtodnp_3">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.ddmtodnp_4">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.ddmtodnp_5">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_6.ddmtodnp_7">\r
+ <processor name="tile_6.magic"/>\r
+ <txbuf name="tile_6.ddm"/>\r
+ <hw_channel name="tile_6.ahb0"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ </writepath>\r
+\r
+\r
+ <!--*****************************************************************-->\r
+ <!-- tile_7 communication paths -->\r
+ <!--*****************************************************************-->\r
+ <writepath name="tile_7.rdmtodxm">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.armbus"/>\r
+ <hw_channel name="tile_7.ahb1"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_7.rdmfromdxm">\r
+ <processor name="tile_7.arm"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ <hw_channel name="tile_7.ahb1"/>\r
+ <hw_channel name="tile_7.armbus"/>\r
+ <rxbuf name="tile_7.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_7.rdmtordm">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.armbus"/>\r
+ <chbuf name="tile_7.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_7.rdmfromrdm">\r
+ <processor name="tile_7.arm"/>\r
+ <chbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.armbus"/>\r
+ <rxbuf name="tile_7.rdm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_7.ddmtoddm">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.magicbus"/>\r
+ <chbuf name="tile_7.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_7.ddmfromddm">\r
+ <processor name="tile_7.magic"/>\r
+ <chbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.magicbus"/>\r
+ <rxbuf name="tile_7.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <writepath name="tile_7.ddmtodxm">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.dma"/>\r
+ <hw_channel name="tile_7.ahb1"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </writepath>\r
+\r
+ <readpath name="tile_7.ddmfromdxm">\r
+ <processor name="tile_7.magic"/>\r
+ <chbuf name="tile_7.dxm"/>\r
+ <hw_channel name="tile_7.ahb1"/>\r
+ <hw_channel name="tile_7.dma"/>\r
+ <rxbuf name="tile_7.ddm"/>\r
+ <configuration name="delay" value="0"/>\r
+ <configuration name="cycles" value="8"/>\r
+ </readpath>\r
+\r
+ <!-- tile_7 ARM inter-tile communication paths -->\r
+ <writepath name="tile_7.rdmtodnp_0">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.rdmtodnp_1">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.rdmtodnp_2">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.rdmtodnp_3">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.rdmtodnp_4">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.rdmtodnp_5">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.rdmtodnp_6">\r
+ <processor name="tile_7.arm"/>\r
+ <txbuf name="tile_7.rdm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+ <!-- tile_7 DSP inter-tile communication paths -->\r
+ <writepath name="tile_7.ddmtodnp_0">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_0.dnp"/>\r
+ <chbuf name="tile_0.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.ddmtodnp_1">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_1.dnp"/>\r
+ <chbuf name="tile_1.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.ddmtodnp_2">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_2.dnp"/>\r
+ <chbuf name="tile_2.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.ddmtodnp_3">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_3.dnp"/>\r
+ <chbuf name="tile_3.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.ddmtodnp_4">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_4.dnp"/>\r
+ <chbuf name="tile_4.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.ddmtodnp_5">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_5.dnp"/>\r
+ <chbuf name="tile_5.dxm"/>\r
+ </writepath>\r
+\r
+ <writepath name="tile_7.ddmtodnp_6">\r
+ <processor name="tile_7.magic"/>\r
+ <txbuf name="tile_7.ddm"/>\r
+ <hw_channel name="tile_7.ahb0"/>\r
+ <hw_channel name="tile_7.dnp"/>\r
+ <hw_channel name="tile_6.dnp"/>\r
+ <chbuf name="tile_6.dxm"/>\r
+ </writepath>\r
+\r
+</architecture>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork
+xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+ http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="example1">
+
+ <!-- processes -->
+ <process name="generator">
+ <port type="output" name="1"/>
+ <source type="c" location="generator.c"/>
+ </process>
+
+ <process name="consumer">
+ <port type="input" name="1"/>
+ <source type="c" location="consumer.c"/>
+ </process>
+
+ <process name="square">
+ <port type="input" name="1"/>
+ <port type="output" name="2"/>
+ <source type="c" location="square.c"/>
+ </process>
+
+ <!-- sw_channels -->
+ <sw_channel type="fifo" size="10" name="C1">
+ <port type="input" name="0"/>
+ <port type="output" name="1"/>
+ </sw_channel>
+
+ <sw_channel type="fifo" size="10" name="C2">
+ <port type="input" name="0"/>
+ <port type="output" name="1"/>
+ </sw_channel>
+
+ <!-- connections -->
+ <connection name="g-c">
+ <origin name="generator">
+ <port name="1"/>
+ </origin>
+ <target name="C1">
+ <port name="0"/>
+ </target>
+ </connection>
+
+ <connection name="c-c">
+ <origin name="C2">
+ <port name="1"/>
+ </origin>
+ <target name="consumer">
+ <port name="1"/>
+ </target>
+ </connection>
+
+ <connection name="s-c">
+ <origin name="square">
+ <port name="2"/>
+ </origin>
+ <target name="C2">
+ <port name="0"/>
+ </target>
+ </connection>
+
+ <connection name="c-s">
+ <origin name="C1">
+ <port name="1"/>
+ </origin>
+ <target name="square">
+ <port name="1"/>
+ </target>
+ </connection>
+
+</processnetwork>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<mapping xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING http://www.tik.ee.ethz.ch/~shapes/schema/mapping.xsd" name="example1_map_1">
+
+<binding name="generator" xsi:type="computation">
+ <process name="generator" />
+ <processor name="sim1" />
+</binding>
+<binding name="consumer" xsi:type="computation">
+ <process name="consumer" />
+ <processor name="sim1" />
+</binding>
+<binding name="square" xsi:type="computation">
+ <process name="square" />
+ <processor name="sim1" />
+</binding>
+</mapping>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<mapping xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING http://www.tik.ee.ethz.ch/~shapes/schema/mapping.xsd" name="example1_map_3">
+
+<binding name="generator" xsi:type="computation">
+ <process name="generator" />
+ <processor name="sim1" />
+</binding>
+<binding name="consumer" xsi:type="computation">
+ <process name="consumer" />
+ <processor name="sim2" />
+</binding>
+<binding name="square" xsi:type="computation">
+ <process name="square" />
+ <processor name="sim3" />
+</binding>
+</mapping>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<mapping xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING
+ http://www.tik.ee.ethz.ch/~shapes/schema/mapping.xsd"
+ name="Example1 on MPARM">
+
+ <binding name="binding_generator" xsi:type="computation">
+ <process name="generator"/>
+ <processor name="processor_1"/>
+ </binding>
+
+ <binding name="binding_square" xsi:type="computation">
+ <process name="square"/>
+ <processor name="processor_0"/>
+ </binding>
+
+ <binding name="binding_consumer" xsi:type="computation">
+ <process name="consumer"/>
+ <processor name="processor_1"/>
+ </binding>
+
+ <schedule name="schedule_0" type="fixedpriority">
+ <resource name="processor_0"/>
+ <origin name="square">
+ <configuration name="priority" value="1"/>
+ </origin>
+ </schedule>
+
+ <schedule name="schedule_1" type="fixedpriority">
+ <resource name="processor_1"/>
+ <origin name="consumer">
+ <configuration name="priority" value="1"/>
+ </origin>
+ <origin name="generator">
+ <configuration name="priority" value="2"/>
+ </origin>
+ </schedule>
+
+</mapping>
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "arragygen.h"
+
+// initialization function
+void arraygen_init(DOLProcess *p) {
+ p->local->index = 0;
+ srand((unsigned) time(NULL));
+ //p->local->len = LENGTH;
+}
+
+int arraygen_fire(DOLProcess *p) {
+
+
+ /* generate a random integer array of length L */
+ //int num = rand() % 1000;
+
+ int i;
+ int len = LENGTH;
+ int * array;
+ array = (int *) malloc(sizeof(int)*len);
+
+ for(i=0;i<len;i++)
+ array[i] = rand() % (len*2);
+
+#if DEBUG
+ for(i=0;i<LENGTH;i++)
+ printf("%d ", array[i]);
+ printf("\n");
+ printf("generated\n");
+#endif
+
+ DOL_write((void*)PORT_OUT1, &(len), sizeof(int), p);
+ DOL_write((void*)PORT_OUT2, array, sizeof(int)*length, p);
+
+ free(array);
+ DOL_detach(p);
+ return -1;
+
+}
--- /dev/null
+#ifndef ARRAYGEN_H
+#define ARRAYGEN_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_OUT1 1
+#define PORT_OUT2 2
+
+
+typedef struct _local_states {
+ int index;
+} Arraygen_State;
+
+void arraygen_init(DOLProcess *);
+int arraygen_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void consumer_init(DOLProcess *p) {
+ sprintf(p->local->name, "consumer");
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int consumer_fire(DOLProcess *p) {
+ float c;
+ if (p->local->index < p->local->len) {
+ DOL_read((void*)PORT_IN, &c, sizeof(float), p);
+ printf("%s: %f\n", p->local->name, c);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN 1
+
+typedef struct _local_states {
+ char name[10];
+ int index;
+ int len;
+} Consumer_State;
+
+void consumer_init(DOLProcess *);
+int consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "generator.h"
+
+// initialization function
+void generator_init(DOLProcess *p) {
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int generator_fire(DOLProcess *p) {
+
+ if (p->local->index < p->local->len) {
+ float x = (float)p->local->index;
+ DOL_write((void*)PORT_OUT, &(x), sizeof(float), p);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef GENERATOR_H
+#define GENERATOR_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_OUT 1
+
+typedef struct _local_states {
+ int index;
+ int len;
+} Generator_State;
+
+void generator_init(DOLProcess *);
+int generator_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#include <stdio.h>
+
+#define ARRAY_LEN 10
+#define DEBUG 1
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "printarray.h"
+
+void printarray_init(DOLProcess *p) {
+ p->local->index = 0;
+}
+
+int printarray_fire(DOLProcess *p) {
+
+ int len;
+ int * array;
+ DOL_read((void*)PORT_IN1, &len, sizeof(int), p);
+ DOL_read((void*)PORT_IN2, array, sizeof(int)*len, p);
+
+ printf("sorted output\n");
+ for(i=0;i<LENGTH;i++)
+ printf("%d ", array[i]);
+ printf("\n");
+
+ free(array);
+ DOL_detach(p);
+ return -1;
+}
+
--- /dev/null
+#ifndef PRINTARRAY_H
+#define PRINTARRAY_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN1 1
+#define PORT_IN2 2
+
+typedef struct _local_states {
+ int index;
+} Printarray_State;
+
+void printarray_init(DOLProcess *);
+int printarray_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <math.h>
+
+#include "quicksort.h"
+
+int smaller_arr(int *dst, int *src, int pivot,int len)
+{
+ int i;
+ int num=0;
+ for(i=0;i<len;i++)
+ {
+ if(src[i]<=pivot)
+ {
+ dst[num++]=src[i];
+ }
+ }
+ return num;
+}
+
+int bigger_arr(int *dst, int *src, int pivot,int len)
+{
+ int i;
+ int num=0;
+ for(i=0;i<len;i++)
+ {
+ if(src[i]>pivot)
+ {
+ dst[num++]=src[i];
+ }
+ }
+ return num;
+}
+
+int median_const(int len, int * array)
+{
+ int i,j;
+ int desired_rank = ceil(len/2);
+
+ for(i=0;i<len;i++)
+ {
+ int rank = 1;
+ for(j=0;j<len;j++)
+ {
+ /* FIXME: exception handling */
+ if(i!=j && array[j]>array[i])
+ rank++;
+ }
+
+ if(rank==desired_rank)
+ return array[i];
+ }
+ return array[0];
+}
+
+int select_med(int size, int * array)
+{
+ int ret;
+ int * array_of_median;
+ int len = ceil(size/5);
+ int i,j;
+
+ /* divide array into groups of five elements */
+ array_of_median = malloc(sizeof(int)*len);
+
+ for(i=0;i<len;i++)
+ {
+ if(i!=len-1)
+ array_of_median[i] = median_const(5,array+5*i);
+ else
+ array_of_median[i] = median_const(len%5,array+5*i);
+ }
+
+ /* call itself recursively */
+ ret = select_med(len, array_of_median);
+
+ /* release */
+ free(array_of_median);
+
+ return ret;
+}
+
+
+
+void quicksort_init(DOLProcess *p) {
+ p->local->index = 0;
+}
+
+int quicksort_fire(DOLProcess *p) {
+
+ int len=LENGTH;
+ int * array;
+ int median;
+ int down,up;
+
+ /* receive the 'size' / 'array' */
+ DOL_read((void*)PORT_IN1, &len, sizeof(int), p);
+ DOL_read((void*)PORT_IN2, array, sizeof(int)*len, p);
+
+ /* selection */
+ median = select_med(len, array);
+
+ /* divide */
+ down = 0; up =0;
+ down=smaller_arr(arr1,array,median,len);
+ up=bigger_arr(arr2,array,median,len);
+
+ // down + up == len
+
+ /* sort */
+ quick
+
+ /* merge */
+
+ /* send the 'size' / 'sorted array' */
+ DOL_write((void*)PORT_OUT1, &len, sizeof(int), p);
+
+ DOL_detach(p);
+ return -1;
+}
+
--- /dev/null
+#ifndef QUICKSORT_H
+#define QUICKSORT_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN1 1
+#define PORT_IN2 2
+#define PORT_OUT1 3
+#define PORT_OUT2 4
+
+typedef struct _local_states {
+ int index;
+ int * arr1;
+ int * arr2;
+} Quicksort_State;
+
+void quicksort_init(DOLProcess *);
+int quicksort_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "square.h"
+
+void square_init(DOLProcess *p) {
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int square_fire(DOLProcess *p) {
+ float i;
+
+ if (p->local->index < p->local->len) {
+ DOL_read((void*)PORT_IN, &i, sizeof(float), p);
+ i = i*i;
+ DOL_write((void*)PORT_OUT, &i, sizeof(float), p);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef SQUARE_H
+#define SQUARE_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN 1
+#define PORT_OUT 2
+
+typedef struct _local_states {
+ int index;
+ int len;
+} Square_State;
+
+void square_init(DOLProcess *);
+int square_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="example2">
+
+ <variable value="3" name="N"/>
+
+ <!-- instantiate resources -->
+ <process name="generator">
+ <port type="output" name="10"/>
+ <source type="c" location="generator.c"/>
+ </process>
+
+ <iterator variable="i" range="N">
+ <process name="square">
+ <append function="i"/>
+ <port type="input" name="0"/>
+ <port type="output" name="1"/>
+ <source type="c" location="square.c"/>
+ </process>
+ </iterator>
+
+ <process name="consumer">
+ <port type="input" name="100"/>
+ <source type="c" location="consumer.c"/>
+ </process>
+
+ <iterator variable="i" range="N + 1">
+ <sw_channel type="fifo" size="10" name="C2">
+ <append function="i"/>
+ <port type="input" name="0"/>
+ <port type="output" name="1"/>
+ </sw_channel>
+ </iterator>
+
+ <!-- instantiate connection -->
+ <iterator variable="i" range="N">
+ <connection name="to_square">
+ <append function="i"/>
+ <origin name="C2">
+ <append function="i"/>
+ <port name="1"/>
+ </origin>
+ <target name="square">
+ <append function="i"/>
+ <port name="0"/>
+ </target>
+ </connection>
+
+ <connection name="from_square">
+ <append function="i"/>
+ <origin name="square">
+ <append function="i"/>
+ <port name="1"/>
+ </origin>
+ <target name="C2">
+ <append function="i + 1"/>
+ <port name="0"/>
+ </target>
+ </connection>
+ </iterator>
+
+ <connection name="g_">
+ <origin name="generator">
+ <port name="10"/>
+ </origin>
+ <target name="C2">
+ <append function="0"/>
+ <port name="0"/>
+ </target>
+ </connection>
+
+ <connection name="_c">
+ <origin name="C2">
+ <append function="N"/>
+ <port name="1"/>
+ </origin>
+ <target name="consumer">
+ <port name="100"/>
+ </target>
+ </connection>
+
+</processnetwork>
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void consumer_init(DOLProcess *p) {
+ sprintf(p->local->name, "consumer");
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int consumer_fire(DOLProcess *p) {
+ float c;
+ if (p->local->index < p->local->len) {
+ DOL_read((void*)PORT_IN, &c, sizeof(float), p);
+ printf("%s: %f\n", p->local->name, c);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN 100
+
+typedef struct _local_states {
+ char name[10];
+ int index;
+ int len;
+} Consumer_State;
+
+void consumer_init(DOLProcess *);
+int consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "generator.h"
+
+// initialization function
+void generator_init(DOLProcess *p) {
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int generator_fire(DOLProcess *p) {
+
+ if (p->local->index < p->local->len) {
+ float x = (float)p->local->index;
+ DOL_write((void*)PORT_OUT, &(x), sizeof(float), p);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef GENERATOR_H
+#define GENERATOR_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_OUT 10
+
+typedef struct _local_states {
+ int index;
+ int len;
+} Generator_State;
+
+void generator_init(DOLProcess *);
+int generator_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#define LENGTH 20
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "square.h"
+
+void square_init(DOLProcess *p) {
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int square_fire(DOLProcess *p) {
+ float i;
+
+ if (p->local->index < p->local->len) {
+ DOL_read((void*)PORT_IN, &i, sizeof(float), p);
+ i = i*i;
+ DOL_write((void*)PORT_OUT, &i, sizeof(float), p);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef SQUARE_H
+#define SQUARE_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN 0
+#define PORT_OUT 1
+
+typedef struct _local_states {
+ int index;
+ int len;
+} Square_State;
+
+void square_init(DOLProcess *);
+int square_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="example3">
+
+ <variable value="3" name="N"/>
+ <variable value="10" name="FIFO_SIZE"/>
+
+ <!-- instantiate resources -->
+ <iterator variable="i" range="N">
+ <process name="horizontal_generator">
+ <append function="i"/>
+ <port type="output" name="h_out"/>
+ <source type="c" location="horizontal_generator.c"/>
+ </process>
+ <process name="horizontal_consumer">
+ <append function="i"/>
+ <port type="input" name="h_in"/>
+ <source type="c" location="horizontal_consumer.c"/>
+ </process>
+ </iterator>
+
+ <iterator variable="i" range="N">
+ <process name="vertical_generator">
+ <append function="i"/>
+ <port type="output" name="v_out"/>
+ <source type="c" location="vertical_generator.c"/>
+ </process>
+ <process name="vertical_consumer">
+ <append function="i"/>
+ <port type="input" name="v_in"/>
+ <source type="c" location="vertical_consumer.c"/>
+ </process>
+ </iterator>
+
+ <iterator variable="i" range="N">
+ <iterator variable="j" range="N">
+ <process name="forward">
+ <append function="i"/>
+ <append function="j"/>
+ <port type="input" name="west"/>
+ <port type="input" name="north"/>
+ <port type="output" name="east"/>
+ <port type="output" name="south"/>
+ <source type="c" location="forward.c"/>
+ </process>
+ </iterator>
+ </iterator>
+
+ <iterator variable="i" range="N + 1">
+ <iterator variable="j" range="N">
+ <sw_channel type="fifo" size="FIFO_SIZE" name="C_h">
+ <append function="i"/>
+ <append function="j"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ <sw_channel type="fifo" size="FIFO_SIZE" name="C_v">
+ <append function="j"/>
+ <append function="i"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ </iterator>
+ </iterator>
+
+ <!-- instantiate connections -->
+ <iterator variable="i" range="N">
+ <iterator variable="j" range="N">
+ <connection name="west">
+ <append function="i"/>
+ <append function="j"/>
+ <origin name="C_h">
+ <append function="i"/>
+ <append function="j"/>
+ <port name="out"/>
+ </origin>
+ <target name="forward">
+ <append function="i"/>
+ <append function="j"/>
+ <port name="west"/>
+ </target>
+ </connection>
+
+ <connection name="east">
+ <append function="i"/>
+ <append function="j"/>
+ <origin name="forward">
+ <append function="i"/>
+ <append function="j"/>
+ <port name="east"/>
+ </origin>
+ <target name="C_h">
+ <append function="i + 1"/>
+ <append function="j"/>
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="north">
+ <append function="i"/>
+ <append function="j"/>
+ <origin name="C_v">
+ <append function="i"/>
+ <append function="j"/>
+ <port name="out"/>
+ </origin>
+ <target name="forward">
+ <append function="i"/>
+ <append function="j"/>
+ <port name="north"/>
+ </target>
+ </connection>
+
+ <connection name="south">
+ <append function="i"/>
+ <append function="j"/>
+ <origin name="forward">
+ <append function="i"/>
+ <append function="j"/>
+ <port name="south"/>
+ </origin>
+ <target name="C_v">
+ <append function="i"/>
+ <append function="j + 1"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+
+ <!-- boundary connections -->
+ <iterator variable="i" range="N">
+ <connection name="west">
+ <append function="i + 1"/>
+ <origin name="horizontal_generator">
+ <append function="i"/>
+ <port name="h_out"/>
+ </origin>
+ <target name="C_h">
+ <append function="0"/>
+ <append function="i"/>
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="east">
+ <append function="i + 1"/>
+ <origin name="C_h">
+ <append function="N"/>
+ <append function="i"/>
+ <port name="out"/>
+ </origin>
+ <target name="horizontal_consumer">
+ <append function="i"/>
+ <port name="h_in"/>
+ </target>
+ </connection>
+
+ <connection name="north">
+ <append function="i + 1"/>
+ <origin name="vertical_generator">
+ <append function="i"/>
+ <port name="v_out"/>
+ </origin>
+ <target name="C_v">
+ <append function="i"/>
+ <append function="0"/>
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="south">
+ <append function="i + 1"/>
+ <origin name="C_v">
+ <append function="i"/>
+ <append function="N"/>
+ <port name="out"/>
+ </origin>
+ <target name="vertical_consumer">
+ <append function="i"/>
+ <port name="v_in"/>
+ </target>
+ </connection>
+ </iterator>
+
+</processnetwork>
--- /dev/null
+#include <stdio.h>
+
+#include "forward.h"
+
+void forward_init(DOLProcess *p) {
+ sprintf(p->local->name,"Forward");
+}
+
+int forward_fire(DOLProcess *p) {
+ char c;
+ char c2;
+
+ DOL_read((void*)PORT_IN1, &c, 1, p);
+ DOL_read((void*)PORT_IN2, &c2, 1, p);
+ DOL_write((void*)PORT_OUT1, &c, 1, p);
+ DOL_write((void*)PORT_OUT2, &c2, 1, p);
+
+ return 0;
+}
--- /dev/null
+#ifndef FORWARD_H
+#define FORWARD_H
+
+#include <dol.h>
+
+#define PORT_IN1 "west"
+#define PORT_IN2 "north"
+#define PORT_OUT1 "east"
+#define PORT_OUT2 "south"
+
+typedef struct _local_states {
+ char name[20];
+} Forward_State;
+
+void forward_init(DOLProcess *);
+int forward_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "horizontal_consumer.h"
+
+void horizontal_consumer_init(DOLProcess *p) {
+ sprintf(p->local->name, "h_consumer");
+}
+
+int horizontal_consumer_fire(DOLProcess *p) {
+ char c;
+ DOL_read((void*)PORT_IN, &c, 1, p);
+ printf("%s: %c\n", p->local->name, c);
+
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+
+#define PORT_IN "h_in"
+
+typedef struct _local_states {
+ char name[20];
+} Horizontal_consumer_State;
+
+void horizontal_consumer_init(DOLProcess *);
+int horizontal_consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "horizontal_generator.h"
+
+// initialization function
+void horizontal_generator_init(DOLProcess *p) {
+ sprintf(p->local->str, "nopqrstuvwxyz");
+ p->local->index = 0;
+ p->local->len = strlen(p->local->str);
+}
+
+int horizontal_generator_fire(DOLProcess *p) {
+
+ if (p->local->index < p->local->len) {
+ DOL_write((void*)PORT_OUT, (p->local->str + p->local->index), 1, p);
+ p->local->index++;
+ }
+ else {
+ DOL_detach(p);
+ }
+ return 0;
+}
+
--- /dev/null
+#ifndef PRODUCER_H
+#define PRODUCER_H
+
+#include <dol.h>
+
+#define PORT_OUT "h_out"
+
+typedef struct _local_states {
+ int index;
+ char str[25];
+ int len;
+} Horizontal_generator_State;
+
+void horizontal_generator_init(DOLProcess *);
+int horizontal_generator_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "vertical_consumer.h"
+
+void vertical_consumer_init(DOLProcess *p) {
+ sprintf(p->local->name, "v_consumer");
+}
+
+int vertical_consumer_fire(DOLProcess *p) {
+ char c;
+ DOL_read((void*)PORT_IN, &c, 1, p);
+ printf("%s: %c\n", p->local->name, c);
+
+ return 0;
+}
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+
+#define PORT_IN "v_in"
+
+typedef struct _local_states {
+ char name[20];
+} Vertical_consumer_State;
+
+void vertical_consumer_init(DOLProcess *);
+int vertical_consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "vertical_generator.h"
+
+// initialization function
+void vertical_generator_init(DOLProcess *p) {
+ sprintf(p->local->str,"abcdefghijklm");
+ p->local->index = 0;
+ p->local->len = strlen(p->local->str);
+}
+
+int vertical_generator_fire(DOLProcess *p) {
+
+ if (p->local->index < p->local->len) {
+ DOL_write((void*)PORT_OUT, (p->local->str + p->local->index), 1, p);
+ p->local->index++;
+ } else {
+ DOL_detach(p);
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef PRODUCER_H
+#define PRODUCER_H
+
+#include <dol.h>
+
+#define PORT_OUT "v_out"
+
+typedef struct _local_states {
+ int index;
+ char str[20];
+ int len;
+} Vertical_generator_State;
+
+void vertical_generator_init(DOLProcess *);
+int vertical_generator_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="MatrixMult">
+
+ <variable value="2" name="N"/> <!-- number of rows/columns of square matrix -->
+
+ <!-- instantiate processes -->
+ <!-- process for generating matrices -->
+ <process name="input_generator">
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <port type="output" name="matrixA">
+ <append function="row"/>
+ <append function="col"/>
+ <append function="i"/>
+ </port>
+ <port type="output" name="matrixB">
+ <append function="row"/>
+ <append function="col"/>
+ <append function="i"/>
+ </port>
+ </iterator>
+ </iterator>
+ </iterator>
+ <iterator variable="i" range="N * N">
+ <port type="output" name="zeroinput">
+ <append function="i"/>
+ </port>
+ </iterator>
+ <source type="c" location="generator.c"/>
+ </process>
+
+ <!-- process to collect result -->
+ <process name="output_consumer">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <port type="input" name="matrixC">
+ <append function="row"/>
+ <append function="col"/>
+ </port>
+ </iterator>
+ </iterator>
+ <source type="c" location="consumer.c"/>
+ </process>
+
+ <!-- processes to compute result -->
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <process name="addmult">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port type="input" name="factor1"/>
+ <port type="input" name="factor2"/>
+ <port type="input" name="summand"/>
+ <port type="output" name="sum"/>
+ <source type="c" location="addmult.c"/>
+ </process>
+ </iterator>
+ </iterator>
+ </iterator>
+
+
+ <!-- instantiate channels -->
+ <!-- channels for matrices -->
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <sw_channel type="fifo" size="8" name="matrixAchannel">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ <sw_channel type="fifo" size="8" name="matrixBchannel">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ </iterator>
+ </iterator>
+ </iterator>
+
+ <!-- channels for zeros -->
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <sw_channel type="fifo" size="8" name="zerochannel">
+ <append function="i"/>
+ <append function="row"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ </iterator>
+ </iterator>
+
+ <!-- channels for result -->
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <sw_channel type="fifo" size="8" name="resultchannel">
+ <append function="row"/>
+ <append function="col"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ </iterator>
+ </iterator>
+
+ <!-- channels between processes -->
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N - 1">
+ <sw_channel type="fifo" size="8" name="addmultchannel">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ </iterator>
+ </iterator>
+ </iterator>
+
+
+ <!-- instantiate connections -->
+ <!-- connect the input_generator to the "matrix" and zero channels -->
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <connection name="tomatrixAchannel">
+ <append function="row"/>
+ <append function="col"/>
+ <append function="i"/>
+ <origin name="input_generator">
+ <port name="matrixA">
+ <append function="row"/>
+ <append function="col"/>
+ <append function="i"/>
+ </port>
+ </origin>
+ <target name="matrixAchannel">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="tomatrixBchannel">
+ <append function="row"/>
+ <append function="col"/>
+ <append function="i"/>
+ <origin name="input_generator">
+ <port name="matrixB">
+ <append function="row"/>
+ <append function="col"/>
+ <append function="i"/>
+ </port>
+ </origin>
+ <target name="matrixBchannel">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ </iterator>
+
+ <connection name="tozerochannel">
+ <append function="i * N + row"/>
+ <origin name="input_generator">
+ <port name="zeroinput">
+ <append function="i * N + row"/>
+ </port>
+ </origin>
+ <target name="zerochannel">
+ <append function="i"/>
+ <append function="row"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+
+ <!-- connect the "matrix" and "zero" channels to the addmults -->
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <!-- connection for matrix A -->
+ <connection name="matrixA_connection">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <origin name="matrixAchannel">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port name="out"/>
+ </origin>
+ <target name="addmult">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port name="factor1"/>
+ </target>
+ </connection>
+
+ <!-- connection for matrix B -->
+ <!-- note the order of appends for matrixBchannel -->
+ <connection name="matrixB_connection">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <origin name="matrixBchannel">
+ <append function="row"/>
+ <append function="col"/>
+ <append function="i"/>
+ <port name="out"/>
+ </origin>
+ <target name="addmult">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port name="factor2"/>
+ </target>
+ </connection>
+ </iterator>
+
+ <!-- zero input connections to addmults -->
+ <connection name="zero_connection">
+ <append function="i"/>
+ <append function="row"/>
+ <origin name="zerochannel">
+ <append function="i"/>
+ <append function="row"/>
+ <port name="out"/>
+ </origin>
+ <target name="addmult">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="0"/>
+ <port name="summand"/>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+
+ <!-- connections from output of addmults to "addmult" channels -->
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N - 1">
+ <connection name="fromaddmult">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <origin name="addmult">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port name="sum"/>
+ </origin>
+ <target name="addmultchannel">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+ </iterator>
+
+ <!-- connections from "addmult" channels to input of addmults -->
+ <iterator variable="i" range="N">
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N - 1">
+ <connection name="toaddmult">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col + 1"/>
+ <origin name="addmultchannel">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col"/>
+ <port name="out"/>
+ </origin>
+ <target name="addmult">
+ <append function="i"/>
+ <append function="row"/>
+ <append function="col + 1"/>
+ <port name="summand"/>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+ </iterator>
+
+ <!-- connections from addmults to "result" channels -->
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <connection name="tomatrixCchannel">
+ <append function="row"/>
+ <append function="col"/>
+ <origin name="addmult">
+ <append function="col"/>
+ <append function="row"/>
+ <append function="N-1"/>
+ <port name="sum"/>
+ </origin>
+ <target name="resultchannel">
+ <append function="row"/>
+ <append function="col"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+
+ <!-- connections from "result" channels to output_consumer -->
+ <iterator variable="row" range="N">
+ <iterator variable="col" range="N">
+ <connection name="frommatrixCchannel">
+ <append function="row"/>
+ <append function="col"/>
+ <origin name="resultchannel">
+ <append function="row"/>
+ <append function="col"/>
+ <port name="out"/>
+ </origin>
+ <target name="output_consumer">
+ <port name="matrixC">
+ <append function="row"/>
+ <append function="col"/>
+ </port>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+
+</processnetwork>
--- /dev/null
+#include <stdio.h>
+#include "addmult.h"
+
+void addmult_init(DOLProcess *p)
+{
+ sprintf(p->local->id, "addmult_%d_%d_%d",
+ GETINDEX(0),
+ GETINDEX(1),
+ GETINDEX(2));
+}
+
+
+int addmult_fire(DOLProcess *p)
+{
+ float factor1, factor2, summand;
+
+ DOL_read((void*)PORT_FACTOR1, &factor1, sizeof(float), p);
+ DOL_read((void*)PORT_FACTOR2, &factor2, sizeof(float), p);
+ DOL_read((void*)PORT_SUMMAND, &summand, sizeof(float), p);
+ p->local->sum = factor1 * factor2 + summand;
+ DOL_write((void*)PORT_SUM, &(p->local->sum), sizeof(float), p);
+
+ printf("%15s: %f * %f + %f = %f\n",
+ p->local->id, factor1, factor2, summand, p->local->sum);
+
+ return 0;
+}
+
--- /dev/null
+#ifndef ADDMULT_H
+#define ADDMULT_H
+
+#include <dol.h>
+
+#define PORT_FACTOR1 "factor1"
+#define PORT_FACTOR2 "factor2"
+#define PORT_SUMMAND "summand"
+#define PORT_SUM "sum"
+
+typedef struct _local_states
+{
+ char id[14];
+ float sum;
+} Addmult_State;
+
+void addmult_init(DOLProcess *);
+int addmult_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#ifndef CONSTANTS_H
+#define CONSTANTS_H
+
+/*
+#define NUMBER_OF_ROWS_COLS 1
+#define MATRIX_A_INITIAL_VALUE { 1.0 }
+#define MATRIX_B_INITIAL_VALUE { 2.5 }
+*/
+
+#define NUMBER_OF_ROWS_COLS 2
+#define MATRIX_A_INITIAL_VALUE { {1.0, 2.0 }, { 3.0, 4.0 } }
+#define MATRIX_B_INITIAL_VALUE { {0.0, -1.0 }, { -2.0, -3.0 } }
+
+/*
+#define NUMBER_OF_ROWS_COLS 3
+#define MATRIX_A_INITIAL_VALUE { {1.0, 2.0, 3.0 }, {4.0, 5.0, -4.0 }, {-3.0, -2.0, -1.0} }
+#define MATRIX_B_INITIAL_VALUE { {1.0, 0.0, 0.0 }, {0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0} }
+*/
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void output_consumer_init(DOLProcess *p)
+{
+ ; //nothing to be done here
+}
+
+int output_consumer_fire(DOLProcess *p)
+{
+ CREATEPORTVAR(port);
+
+ for (p->local->row = 0; p->local->row < NUMBER_OF_ROWS_COLS; p->local->row++)
+ {
+ for (p->local->col = 0; p->local->col < NUMBER_OF_ROWS_COLS; p->local->col++)
+ {
+ CREATEPORT(port, PORT_MATRIXC, 2,
+ p->local->row, NUMBER_OF_ROWS_COLS,
+ p->local->col, NUMBER_OF_ROWS_COLS);
+
+ DOL_read((void*)port, &p->local->matrixC_value, sizeof(float), p);
+ printf("%15s: matrixC[%d][%d]: %f\n",
+ "output_consumer", p->local->row, p->local->col, p->local->matrixC_value);
+ }
+ }
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include "constants.h"
+#include <dol.h>
+
+#define PORT_MATRIXC "matrixC"
+
+typedef struct _local_states
+{
+ unsigned row, col;
+ float matrixC_value;
+} Output_consumer_State;
+
+void output_consumer_init(DOLProcess *);
+int output_consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "generator.h"
+
+
+Input_generator_State input_generator_state =
+ { matrixA: MATRIX_A_INITIAL_VALUE, matrixB: MATRIX_B_INITIAL_VALUE };
+
+void input_generator_init(DOLProcess *p)
+{
+ for (p->local->row = 0; p->local->row < NUMBER_OF_ROWS_COLS; p->local->row++)
+ {
+ for (p->local->col = 0; p->local->col < NUMBER_OF_ROWS_COLS; p->local->col++)
+ {
+ p->local->matrixA[p->local->row][p->local->col] = (NUMBER_OF_ROWS_COLS * p->local->row) + p->local->col + 1;
+ p->local->matrixB[p->local->row][p->local->col] = -((NUMBER_OF_ROWS_COLS * p->local->row) + p->local->col);
+ }
+ }
+}
+
+
+int input_generator_fire(DOLProcess *p)
+{
+ CREATEPORTVAR(port);
+
+ for (p->local->row = 0; p->local->row < NUMBER_OF_ROWS_COLS; p->local->row++)
+ {
+ for (p->local->col = 0; p->local->col < NUMBER_OF_ROWS_COLS; p->local->col++)
+ {
+ CREATEPORT(port, PORT_ZEROINPUT, 1,
+ p->local->row * NUMBER_OF_ROWS_COLS + p->local->col, NUMBER_OF_ROWS_COLS
+ * NUMBER_OF_ROWS_COLS);
+ printf("%15s: Write to zeroinput_%d: %f\n", "input_generator",
+ p->local->row * NUMBER_OF_ROWS_COLS + p->local->col, 0.0);
+ DOL_write((void*)port, &(p->local->zero), sizeof(float), p);
+
+ for (p->local->i = 0; p->local->i < NUMBER_OF_ROWS_COLS; p->local->i++)
+ {
+ CREATEPORT(port, PORT_MATRIXA, 3,
+ p->local->row, NUMBER_OF_ROWS_COLS,
+ p->local->col, NUMBER_OF_ROWS_COLS,
+ p->local->i, NUMBER_OF_ROWS_COLS);
+ printf("%15s: Write to matrixA_%d_%d_%d: %f\n",
+ "input_generator", p->local->i, p->local->row, p->local->col,
+ p->local->matrixA[p->local->row][p->local->col]);
+ DOL_write((void*)port, &(p->local->matrixA[p->local->row][p->local->col]),
+ sizeof(float), p);
+ CREATEPORT(port, PORT_MATRIXB, 3,
+ p->local->row, NUMBER_OF_ROWS_COLS,
+ p->local->col, NUMBER_OF_ROWS_COLS,
+ p->local->i, NUMBER_OF_ROWS_COLS);
+ printf("%15s: Write to matrixB_%d_%d_%d: %f\n",
+ "input_generator", p->local->i, p->local->row, p->local->col,
+ p->local->matrixB[p->local->row][p->local->col]);
+ DOL_write((void*)port, &(p->local->matrixB[p->local->row][p->local->col]),
+ sizeof(float), p);
+ }
+ }
+ }
+
+ DOL_detach(p);
+ return -1;
+}
+
--- /dev/null
+#ifndef PRODUCER_H
+#define PRODUCER_H
+
+#include "constants.h"
+#include <dol.h>
+
+#define PORT_MATRIXA "matrixA"
+#define PORT_MATRIXB "matrixB"
+#define PORT_ZEROINPUT "zeroinput"
+
+typedef struct _local_states
+{
+ float matrixA[NUMBER_OF_ROWS_COLS][NUMBER_OF_ROWS_COLS];
+ float matrixB[NUMBER_OF_ROWS_COLS][NUMBER_OF_ROWS_COLS];
+ int row, col, i;
+ float zero;
+} Input_generator_State;
+
+void input_generator_init(DOLProcess *);
+int input_generator_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="FFT">
+
+ <!--
+ N is the number of FFT points
+ number_of_layers = ld(N)
+ processes_per_layer = N/2
+ -->
+
+ <!--
+ <variable value="4" name="N"/>
+ <variable value="2" name="NUMBER_OF_LAYERS"/>
+ <variable value="2" name="PROCESSES_PER_LAYER"/>
+ -->
+
+ <!--
+ <variable value="8" name="N"/>
+ <variable value="3" name="NUMBER_OF_LAYERS"/>
+ <variable value="4" name="PROCESSES_PER_LAYER"/>
+ -->
+
+ <variable value="16" name="N"/>
+ <variable value="4" name="NUMBER_OF_LAYERS"/>
+ <variable value="8" name="PROCESSES_PER_LAYER"/>
+
+ <!--
+ <variable value="32" name="N"/>
+ <variable value="5" name="NUMBER_OF_LAYERS"/>
+ <variable value="16" name="PROCESSES_PER_LAYER"/>
+ -->
+
+ <!--
+ <variable value="64" name="N"/>
+ <variable value="6" name="NUMBER_OF_LAYERS"/>
+ <variable value="32" name="PROCESSES_PER_LAYER"/>
+ -->
+
+ <!--
+ <variable value="128" name="N"/>
+ <variable value="7" name="NUMBER_OF_LAYERS"/>
+ <variable value="64" name="PROCESSES_PER_LAYER"/>
+ -->
+
+ <!--
+ <variable value="256" name="N"/>
+ <variable value="8" name="NUMBER_OF_LAYERS"/>
+ <variable value="128" name="PROCESSES_PER_LAYER"/>
+ -->
+
+ <function>
+ <![CDATA[
+ public static int bitreverse(int n, int N)
+ {
+ String numberString = Integer.toString(n, 2); //binary representation of n
+
+ //prepend zeros until string is N characters long
+ while (numberString.length() < N)
+ {
+ numberString = "0" + numberString;
+ }
+
+ //reverse the string
+ char[] numberCharArray = numberString.toCharArray();
+ for (int count = 0; count < numberCharArray.length / 2; count++)
+ {
+ char help = numberCharArray[count];
+ numberCharArray[count] = numberCharArray[N - 1 - count];
+ numberCharArray[N - 1 - count] = help;
+ }
+
+ //convert back to integer
+ return Integer.valueOf(String.valueOf(numberCharArray), 2);
+ }
+ ]]>
+ </function>
+
+ <function>
+ <![CDATA[
+ public static int butterfly(int layer, int p, int addOffset)
+ {
+ int index = 2 * (p % (1 << (layer - 1))) +
+ p / (1 << (layer - 1)) +
+ (p / (1 << layer)) * ((1 << (layer + 1)) - 2);
+
+ if (addOffset == 1)
+ return index + (1 << layer);
+
+ return index;
+ }
+ ]]>
+ </function>
+
+ <!-- instantiate processes -->
+ <process name="generator">
+ <iterator variable="i" range="N">
+ <port type="output" name="input_coefficients">
+ <append function="i"/>
+ </port>
+ </iterator>
+ <source type="c" location="generator.c"/>
+ </process>
+
+ <process name="consumer">
+ <iterator variable="i" range="N">
+ <port type="input" name="output_coefficients">
+ <append function="i"/>
+ </port>
+ </iterator>
+ <source type="c" location="consumer.c"/>
+ </process>
+
+ <iterator variable="i" range="NUMBER_OF_LAYERS">
+ <iterator variable="j" range="PROCESSES_PER_LAYER">
+ <process name="fft2">
+ <append function="i"/>
+ <append function="j"/>
+ <port type="input" name="inA"/>
+ <port type="input" name="inB"/>
+ <port type="output" name="outA"/>
+ <port type="output" name="outB"/>
+ <source type="c" location="fft2.c"/>
+ </process>
+ </iterator>
+ </iterator>
+
+ <!-- instantiate channels -->
+ <!-- channels for input and output coefficients -->
+ <iterator variable="i" range="N">
+ <sw_channel type="fifo" size="16" name="inputchannel">
+ <append function="i"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ <sw_channel type="fifo" size="16" name="outputchannel">
+ <append function="i"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ </iterator>
+
+ <!-- channels for butterfly network -->
+ <iterator variable="layer" range="NUMBER_OF_LAYERS - 1">
+ <iterator variable="i" range="N">
+ <sw_channel type="fifo" size="16" name="butterflychannel">
+ <append function="layer"/>
+ <append function="i"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ </iterator>
+ </iterator>
+
+ <!-- instantiate connections -->
+ <!-- connections from input generator to input channel and from output channel to output consumer -->
+ <iterator variable="i" range="N">
+ <connection name="input_connection">
+ <append function="i"/>
+ <origin name="generator">
+ <port name="input_coefficients">
+ <append function="i"/>
+ </port>
+ </origin>
+ <target name="inputchannel">
+ <append function="i"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ <connection name="output_connection">
+ <append function="i"/>
+ <origin name="outputchannel">
+ <append function="i"/>
+ <port name="out"/>
+ </origin>
+ <target name="consumer">
+ <port name="output_coefficients">
+ <append function="i"/>
+ </port>
+ </target>
+ </connection>
+ </iterator>
+
+ <!-- connections from FFT2 to channels -->
+ <iterator variable="layer" range="NUMBER_OF_LAYERS - 1">
+ <iterator variable="i" range="PROCESSES_PER_LAYER">
+ <connection name="layerkconnection_A">
+ <append function="layer + 1"/>
+ <append function="i"/>
+ <origin name="fft2">
+ <append function="layer"/>
+ <append function="i"/>
+ <port name="outA"/>
+ </origin>
+ <target name="butterflychannel">
+ <append function="layer"/>
+ <append function="2 * i"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ <connection name="layerkconnection_B">
+ <append function="layer + 1"/>
+ <append function="i"/>
+ <origin name="fft2">
+ <append function="layer"/>
+ <append function="i"/>
+ <port name="outB"/>
+ </origin>
+ <target name="butterflychannel">
+ <append function="layer"/>
+ <append function="2 * i + 1"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+
+ <!-- connections from channels to FFT2 -->
+ <!-- connections from input channels to first FFT layer -->
+ <iterator variable="i" range="PROCESSES_PER_LAYER">
+ <connection name="layer1connection_A">
+ <append function="i"/>
+ <origin name="inputchannel">
+ <append function="bitreverse(2 * i, NUMBER_OF_LAYERS)"/>
+ <port name="out"/>
+ </origin>
+ <target name="fft2_0">
+ <append function="i"/>
+ <port name="inA"/>
+ </target>
+ </connection>
+ <connection name="layer1connection_B">
+ <append function="i"/>
+ <origin name="inputchannel">
+ <append function="bitreverse(2 * i + 1, NUMBER_OF_LAYERS)"/>
+ <port name="out"/>
+ </origin>
+ <target name="fft2_0">
+ <append function="i"/>
+ <port name="inB"/>
+ </target>
+ </connection>
+ </iterator>
+
+ <!-- connections from last FFT layer to output channels -->
+ <iterator variable="i" range="PROCESSES_PER_LAYER">
+ <connection name="lastlayerconnection_A">
+ <append function="i"/>
+ <origin name="fft2">
+ <append function="NUMBER_OF_LAYERS - 1"/>
+ <append function="i"/>
+ <port name="outA"/>
+ </origin>
+ <target name="outputchannel">
+ <append function="i"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ <connection name="lastlayerconnection_B">
+ <append function="i"/>
+ <origin name="fft2">
+ <append function="NUMBER_OF_LAYERS - 1"/>
+ <append function="i"/>
+ <port name="outB"/>
+ </origin>
+ <target name="outputchannel">
+ <append function="i + PROCESSES_PER_LAYER"/>
+ <port name="in"/>
+ </target>
+ </connection>
+ </iterator>
+
+ <!-- other connections -->
+ <iterator variable="layer" range="NUMBER_OF_LAYERS - 1">
+ <iterator variable="i" range="PROCESSES_PER_LAYER">
+ <connection name="FFTconnection_A">
+ <append function="layer"/>
+ <append function="i"/>
+ <origin name="butterflychannel">
+ <append function="layer"/>
+ <append function="butterfly(layer + 1, i, 0)"/>
+ <port name="out"/>
+ </origin>
+ <target name="fft2">
+ <append function="layer + 1"/>
+ <append function="i"/>
+ <port name="inA"/>
+ </target>
+ </connection>
+ <connection name="FFTconnection_B">
+ <append function="layer"/>
+ <append function="i"/>
+ <origin name="butterflychannel">
+ <append function="layer"/>
+ <append function="butterfly(layer + 1, i, 1)"/>
+ <port name="out"/>
+ </origin>
+ <target name="fft2">
+ <append function="layer + 1"/>
+ <append function="i"/>
+ <port name="inB"/>
+ </target>
+ </connection>
+ </iterator>
+ </iterator>
+</processnetwork>
--- /dev/null
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Matlab script to compute the reference result for the FFT example.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+close all;
+clear all;
+clc;
+
+wNk = inline('exp(-j * 2 * pi * k / N)', 'N', 'k');
+
+%coefficients produced by c's random number generator in producer_fire()
+x = [ -9 + j * 4
+ -2 + j * 0
+ -3 + j * 0
+ 8 + j * 3
+ 6 + j * 0
+ -7 + j * -9
+ -5 + j * 2
+ 1 + j * 2
+ 8 + j * -4
+ -6 + j * -4
+ 9 + j * -2
+ -8 + j * -4
+ -3 + j * 1
+ -9 + j * 7
+ -9 + j * -9
+ -7 + j * 7
+ 4 + j * -6
+ 5 + j * -5
+ 4 + j * 8
+ 7 + j * -6
+ -3 + j * 9
+ -6 + j * -2
+ -8 + j * -9
+ 2 + j * 7
+ -5 + j * -7
+ 7 + j * -9
+ 0 + j * 9
+ 5 + j * 1
+ -8 + j * 1
+ 5 + j * 6
+ -2 + j * -8
+ 6 + j * -8
+ -5 + j * 7
+ 5 + j * -9
+ 8 + j * -5
+ -6 + j * 9
+ 2 + j * -3
+ 3 + j * -6
+ 5 + j * 0
+ -7 + j * 6
+ 3 + j * -4
+ -2 + j * 4
+ -4 + j * -2
+ 9 + j * -8
+ -3 + j * 3
+ 0 + j * -6
+ 6 + j * 4
+ -2 + j * -4
+ 9 + j * 0
+ -8 + j * -9
+ 0 + j * -4
+ 7 + j * -4
+ 8 + j * 6
+ -2 + j * -1
+ -8 + j * 6
+ 9 + j * -3
+ 1 + j * 4
+ 3 + j * -3
+ 2 + j * -2
+ 9 + j * 6
+ -8 + j * -7
+ -7 + j * 2
+ 8 + j * -1
+ 1 + j * 0
+ -1 + j * -3
+ 3 + j * -9
+ 1 + j * 9
+ -2 + j * 8
+ 8 + j * -5
+ 6 + j * 4
+ 8 + j * 3
+ 9 + j * 9
+ 3 + j * -9
+ 4 + j * -5
+ 4 + j * -2
+ 8 + j * 2
+ -3 + j * 1
+ -8 + j * -9
+ 4 + j * 6
+ 4 + j * 7
+ 2 + j * 7
+ -4 + j * -6
+ 6 + j * 9
+ 3 + j * -5
+ 6 + j * -7
+ -4 + j * -6
+ 3 + j * -1
+ 5 + j * 8
+ 6 + j * -6
+ -5 + j * 0
+ 2 + j * -2
+ -2 + j * -5
+ -4 + j * -8
+ 9 + j * -5
+ 3 + j * 3
+ -3 + j * -9
+ -5 + j * -7
+ 6 + j * -6
+ -9 + j * -3
+ 1 + j * -9
+ 3 + j * -5
+ 3 + j * 9
+ 8 + j * -9
+ -8 + j * 3
+ 1 + j * -5
+ 9 + j * 4
+ -6 + j * 7
+ 3 + j * 5
+ 9 + j * 9
+ -4 + j * -6
+ -1 + j * -8
+ -6 + j * 3
+ 4 + j * -3
+ -6 + j * -7
+ 2 + j * -3
+ -8 + j * 0
+ 1 + j * 9
+ 9 + j * 0
+ -3 + j * 2
+ -2 + j * 7
+ 8 + j * -9
+ 1 + j * 6
+ -4 + j * -1
+ 5 + j * -1
+ 8 + j * 9
+ 3 + j * -9
+ 8 + j * 3
+ -3 + j * -2 ];
+
+fft(x(1:8))
+fft(x(1:16))
+fft(x(1:64))
+fft(x)
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void consumer_init(DOLProcess *p)
+{
+ ; //nothing to be done here
+}
+
+int consumer_fire(DOLProcess *p)
+{
+ CREATEPORTVAR(input_port);
+
+ for (p->local->index = 0; p->local->index < NUMBER_OF_FFT_POINTS;
+ p->local->index++) {
+ CREATEPORT(input_port, PORT_OUTPUT_COEFFICIENTS, 1,
+ p->local->index, NUMBER_OF_FFT_POINTS);
+ DOL_read((void*)input_port, &(p->local->coeffs[p->local->index]),
+ sizeof(ComplexNumber), p);
+ printf("%15s: coeff[%d]: %9f + j * %9f\n",
+ "output_consumer", p->local->index,
+ p->local->coeffs[p->local->index].real,
+ p->local->coeffs[p->local->index].imag);
+ }
+
+ DOL_detach(p);
+ return -1;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_OUTPUT_COEFFICIENTS "output_coefficients"
+
+typedef struct _local_states
+{
+ int index;
+ ComplexNumber coeffs[NUMBER_OF_FFT_POINTS];
+} Consumer_State;
+
+void consumer_init(DOLProcess *);
+int consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <math.h>
+#include "fft2.h"
+
+/**
+ * Determines the twiddle factor of this 2-point FFT based on the
+ * indices of the process.
+ */
+void fft2_init(DOLProcess *p)
+{
+ const float PI = 2.0 * asin(1.0);
+ int layer_index = GETINDEX(0);
+ int process_index = GETINDEX(1);
+ float exponent = 2.0 * PI *
+ (float)(process_index % (1 << layer_index)) /
+ (float)(1 << (layer_index + 1));
+
+ sprintf(p->local->id, "FFT2_%d_%d",
+ GETINDEX(0),
+ GETINDEX(1));
+ p->local->twiddle_factor.real = cos(exponent);
+ p->local->twiddle_factor.imag = -sin(exponent);
+
+ printf("%15s: twiddle_factor %9f + j * %9f\n",
+ p->local->id,
+ p->local->twiddle_factor.real,
+ p->local->twiddle_factor.imag);
+}
+
+/**
+ * Computes 2-point FFT.
+ */
+int fft2_fire(DOLProcess *p)
+{
+ DOL_read((void*)PORT_INA, &(p->local->inA), sizeof(ComplexNumber), p);
+ DOL_read((void*)PORT_INB, &(p->local->inB), sizeof(ComplexNumber), p);
+
+ p->local->rotated_inB.real = p->local->inB.real
+ * p->local->twiddle_factor.real
+ - p->local->inB.imag
+ * p->local->twiddle_factor.imag ;
+ p->local->rotated_inB.imag = p->local->inB.real
+ * p->local->twiddle_factor.imag
+ + p->local->inB.imag
+ * p->local->twiddle_factor.real;
+
+ p->local->outA.real = p->local->inA.real
+ + p->local->rotated_inB.real;
+ p->local->outA.imag = p->local->inA.imag
+ + p->local->rotated_inB.imag;
+
+ p->local->outB.real = p->local->inA.real
+ - p->local->rotated_inB.real;
+ p->local->outB.imag = p->local->inA.imag
+ - p->local->rotated_inB.imag;
+
+ DOL_write((void*)PORT_OUTA, &(p->local->outA), sizeof(ComplexNumber), p);
+ DOL_write((void*)PORT_OUTB, &(p->local->outB), sizeof(ComplexNumber), p);
+
+ /*
+ printf("%15s: ", p->local->id);
+ printf("%9f + j * %9f, %9f + j * %9f => %9f + j * %9f, %9f + j * %9f\n",
+ p->local->inA.real,
+ p->local->inA.imag,
+ p->local->inB.real,
+ p->local->inB.imag,
+ p->local->outA.real,
+ p->local->outA.imag,
+ p->local->outB.real,
+ p->local->outB.imag);
+ */
+
+ DOL_detach(p);
+ return -1;
+}
--- /dev/null
+#ifndef FFT2_H
+#define FFT2_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_INA "inA"
+#define PORT_INB "inB"
+#define PORT_OUTA "outA"
+#define PORT_OUTB "outB"
+
+typedef struct _local_states
+{
+ char id[14];
+ ComplexNumber inA, inB, outA, outB, rotated_inB, twiddle_factor;
+} Fft2_State;
+
+void fft2_init(DOLProcess *);
+int fft2_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "generator.h"
+
+/**
+ * Returns a random integer in the range between lower_bound and
+ * upper_bound, where the bounding values are included in the interval.
+ */
+int getRandomNumber(int lower_bound, int upper_bound)
+{
+ return (rand() % (upper_bound - lower_bound + 1)) + lower_bound;
+}
+
+
+void generator_init(DOLProcess *p)
+{
+ ; //nothing to be done here
+}
+
+
+int generator_fire(DOLProcess *p)
+{
+ CREATEPORTVAR(output_port);
+
+ srand(0); //initialize random number generator
+
+ //generate input coefficients and write them to output ports
+ for (p->local->index = 0;
+ p->local->index < NUMBER_OF_FFT_POINTS;
+ p->local->index++) {
+ p->local->coeffs[p->local->index].real = (float)getRandomNumber(-9, 9);
+ p->local->coeffs[p->local->index].imag = (float)getRandomNumber(-9, 9);
+
+ CREATEPORT(output_port, PORT_INPUT_COEFFICIENTS, 1,
+ p->local->index, NUMBER_OF_FFT_POINTS);
+ printf("%15s: Write to input_coefficients_%d: %9f + j * %9f\n",
+ "input_generator", p->local->index,
+ p->local->coeffs[p->local->index].real,
+ p->local->coeffs[p->local->index].imag);
+ DOL_write((void*)output_port, &(p->local->coeffs[p->local->index]),
+ sizeof(ComplexNumber), p);
+ }
+
+ DOL_detach(p);
+ return -1;
+}
+
--- /dev/null
+#ifndef PRODUCER_H
+#define PRODUCER_H
+
+#include <dol.h>
+#include "global.h"
+#include "stdlib.h"
+
+#define PORT_INPUT_COEFFICIENTS "input_coefficients"
+
+typedef struct _local_states
+{
+ int index;
+ ComplexNumber coeffs[NUMBER_OF_FFT_POINTS];
+} Generator_State;
+
+void generator_init(DOLProcess *);
+int generator_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#define NUMBER_OF_FFT_POINTS 16
+
+//structure for holding complex numbers
+typedef struct complex_number
+{
+ float real;
+ float imag;
+} ComplexNumber;
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="filter">
+
+ <!-- instantiate processes -->
+ <process name="producer">
+ <port type="output" name="out"/>
+ <source type="c" location="producer.c"/>
+ </process>
+
+ <process name="consumer">
+ <port type="input" name="in"/>
+ <source type="c" location="consumer.c"/>
+ </process>
+
+ <process name="filter">
+ <port type="input" name="inA"/>
+ <port type="input" name="inB"/>
+ <port type="output" name="outA"/>
+ <port type="output" name="outB"/>
+ <source type="c" location="filter.c"/>
+ </process>
+
+ <sw_channel type="fifo" size="4" name="inputchannel">
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <sw_channel type="fifo" size="4" name="outputchannel">
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <sw_channel type="fifo" size="4" name="filterchannel">
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <connection name="inputconnection">
+ <origin name="producer">
+ <port name="out"/>
+ </origin>
+ <target name="inputchannel">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="outputconnection">
+ <origin name="outputchannel">
+ <port name="out"/>
+ </origin>
+ <target name="consumer">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="filterconnectionin">
+ <origin name="inputchannel">
+ <port name="out"/>
+ </origin>
+ <target name="filter">
+ <port name="inA"/>
+ </target>
+ </connection>
+
+ <connection name="filterconnectionout">
+ <origin name="filter">
+ <port name="outA"/>
+ </origin>
+ <target name="outputchannel">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <!-- feedback connection -->
+ <connection name="filterconnectionfeedbackA">
+ <origin name="filter">
+ <port name="outB"/>
+ </origin>
+ <target name="filterchannel">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="filterconnectionfeedbackB">
+ <origin name="filterchannel">
+ <port name="out"/>
+ </origin>
+ <target name="filter">
+ <port name="inB"/>
+ </target>
+ </connection>
+
+</processnetwork>
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void consumer_init(DOLProcess *p)
+{
+ ; //nothing to be done here
+}
+
+int consumer_fire(DOLProcess *p)
+{
+ static int index;
+ static float sample;
+
+ for (index = 0; index < 10; index++)
+ {
+ DOL_read((void*)PORT_IN, &sample, sizeof(float), p);
+ printf("%8s: Read sample[%02d]: %+6.4f\n",
+ "consumer", index, sample);
+ }
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+
+#define PORT_IN "in"
+
+typedef struct _local_states
+{
+} Consumer_State;
+
+void consumer_init(DOLProcess *);
+int consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <math.h>
+#include "filter.h"
+
+/**
+ * Write zero to feedback output.
+ */
+void filter_init(DOLProcess *p)
+{
+ p->local->zero = 0.0;
+ p->local->factor = 0.5;
+ p->local->firstiteration = 1;
+}
+
+/**
+ * Filter.
+ */
+int filter_fire(DOLProcess *p)
+{
+ if (p->local->firstiteration) {
+ DOL_write((void*)PORT_OUTB, &(p->local->zero), sizeof(float), p);
+ p->local->firstiteration = 0;
+ }
+
+ DOL_read((void*)PORT_INA, &(p->local->inA), sizeof(float), p);
+ DOL_read((void*)PORT_INB, &(p->local->inB), sizeof(float), p);
+ p->local->out = p->local->inA + p->local->factor * p->local->inB;
+ DOL_write((void*)PORT_OUTA, &(p->local->out), sizeof(float), p);
+ DOL_write((void*)PORT_OUTB, &(p->local->out), sizeof(float), p);
+
+ return 0;
+}
--- /dev/null
+#ifndef FILTER_H
+#define FILTER_H
+
+#include <dol.h>
+
+#define PORT_INA "inA"
+#define PORT_INB "inB"
+#define PORT_OUTA "outA"
+#define PORT_OUTB "outB"
+
+typedef struct _local_states
+{
+ int firstiteration;
+ float inA, inB, out, zero, factor;
+} Filter_State;
+
+void filter_init(DOLProcess *);
+int filter_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "producer.h"
+
+/**
+ * Returns a random integer in the range between lower_bound and
+ * upper_bound, where the bounding values are included in the interval.
+ */
+int getRandomNumber(int lower_bound, int upper_bound)
+{
+ return (rand() % (upper_bound - lower_bound + 1)) + lower_bound;
+}
+
+
+void producer_init(DOLProcess *p)
+{
+ ; //nothing to be done here
+}
+
+
+int producer_fire(DOLProcess *p)
+{
+ static int index;
+
+ srand(0); //initialize random number generator
+
+ //generate input samples and display them
+ printf("producer: samples = { ");
+
+ for (index = 0; index < 10; index++) {
+ p->local->sample[index] = (float) getRandomNumber(-9, 9);
+ if (index < 9) {
+ printf("%+3.1f, ", p->local->sample[index]);
+ }
+ else {
+ printf("%+3.1f }\n", p->local->sample[index]);
+ }
+ }
+
+ //write samples to output port
+ for (index = 0; index < 10; index++) {
+ printf("%8s: Write sample[%02d]: %+6.4f\n",
+ "producer", index, p->local->sample[index]);
+ DOL_write((void*)PORT_OUT, &(p->local->sample[index]),
+ sizeof(float), p);
+ }
+
+ DOL_detach(p);
+ return -1;
+}
+
--- /dev/null
+#ifndef PRODUCER_H
+#define PRODUCER_H
+
+#include <dol.h>
+#include "stdlib.h"
+
+#define PORT_OUT "out"
+
+typedef struct _local_states
+{
+ float sample[10];
+} Producer_State;
+
+void producer_init(DOLProcess *);
+int producer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="filter">
+
+ <!-- N - 1 is the filter order -->
+ <variable name="N" value="3"/>
+
+ <!-- instantiate processes -->
+ <process name="producer">
+ <port type="output" name="out"/>
+ <source type="c" location="producer.c"/>
+ </process>
+
+ <process name="consumer">
+ <port type="input" name="in"/>
+ <source type="c" location="consumer.c"/>
+ </process>
+
+ <iterator variable="i" range="N">
+ <process name="filter">
+ <append function="i"/>
+ <port type="input" name="inA"/>
+ <port type="input" name="inB"/>
+ <port type="output" name="outA"/>
+ <port type="output" name="outB"/>
+ <source type="c" location="filter.c"/>
+ </process>
+ </iterator>
+
+ <!-- instantiate sw_channels -->
+ <sw_channel type="fifo" size="4" name="inputchannel">
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <sw_channel type="fifo" size="4" name="outputchannel">
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <iterator variable="i" range="N - 1">
+ <sw_channel type="fifo" size="4" name="filterchannelA">
+ <append function="i"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <sw_channel type="fifo" size="4" name="filterchannelB">
+ <append function="i"/>
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+ </iterator>
+
+ <sw_channel type="fifo" size="4" name="feedbackchannel">
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <!-- connections of top filter stage -->
+ <connection name="inputconnection">
+ <origin name="producer">
+ <port name="out"/>
+ </origin>
+ <target name="inputchannel">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="outputconnection">
+ <origin name="outputchannel">
+ <port name="out"/>
+ </origin>
+ <target name="consumer">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="filterconnectionin">
+ <origin name="inputchannel">
+ <port name="out"/>
+ </origin>
+ <target name="filter">
+ <append function="0"/>
+ <port name="inA"/>
+ </target>
+ </connection>
+
+ <connection name="filterconnectionout">
+ <origin name="filter">
+ <append function="0"/>
+ <port name="outB"/>
+ </origin>
+ <target name="outputchannel">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <!-- connections of intermediate filter stage(s) -->
+ <iterator variable="i" range="N - 1">
+ <connection name="filterconnectionoutAinA1">
+ <append function="i"/>
+ <origin name="filter">
+ <append function="i"/>
+ <port name="outA"/>
+ </origin>
+ <target name="filterchannelA">
+ <append function="i"/>
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="filterconnectionoutAinA2">
+ <append function="i"/>
+ <origin name="filterchannelA">
+ <append function="i"/>
+ <port name="out"/>
+ </origin>
+ <target name="filter">
+ <append function="i + 1"/>
+ <port name="inA"/>
+ </target>
+ </connection>
+
+ <connection name="filterconnectionoutBinB1">
+ <append function="i"/>
+ <origin name="filter">
+ <append function="i + 1"/>
+ <port name="outB"/>
+ </origin>
+ <target name="filterchannelB">
+ <append function="i"/>
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="filterconnectionoutBinB2">
+ <append function="i"/>
+ <origin name="filterchannelB">
+ <append function="i"/>
+ <port name="out"/>
+ </origin>
+ <target name="filter">
+ <append function="i"/>
+ <port name="inB"/>
+ </target>
+ </connection>
+ </iterator>
+
+ <!-- connection of bottom filter stage -->
+ <connection name="sinkconnectionA1">
+ <origin name="filter">
+ <append function="N - 1"/>
+ <port name="outA"/>
+ </origin>
+ <target name="feedbackchannel">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="sinkconnectionA2">
+ <origin name="feedbackchannel">
+ <port name="out"/>
+ </origin>
+ <target name="filter">
+ <append function="N - 1"/>
+ <port name="inB"/>
+ </target>
+ </connection>
+</processnetwork>
--- /dev/null
+clear all;
+close all;
+clc;
+
+N = 3;
+NUMBER_OF_SAMPLES = 5;
+FILTER_COEFFICIENTS = [0.1 -0.1 0.4 1.0 -0.7 0.2 -0.9 -0.4 -0.8];
+x = [-9 4 -2 0 -3 0 8 3 6 0, ...
+ -7 -9 -5 2 1 2 8 -4 -6 -4];
+
+%example 6
+y = filter(1, [1 -0.5], x(1:10))
+
+%example 7
+y = filter(1, [1 -FILTER_COEFFICIENTS(1:N-1)], x (1:NUMBER_OF_SAMPLES))
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void consumer_init(DOLProcess *p)
+{
+ printf("init consumer.\n");
+}
+
+int consumer_fire(DOLProcess *p)
+{
+ static int index;
+ static float sample;
+
+ for (index = 0; index < NUMBER_OF_SAMPLES; index++)
+ {
+ DOL_read((void*)PORT_IN, &sample, sizeof(float), p);
+ printf("%8s: Read sample[%02d]: %+6.4f\n",
+ "consumer", index, sample);
+ }
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN "in"
+
+typedef struct _local_states
+{
+} Consumer_State;
+
+void consumer_init(DOLProcess *);
+int consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include "filter.h"
+
+/**
+ * Init.
+ */
+void filter_init(DOLProcess *p)
+{
+ int k;
+ p->local->process_index = GETINDEX(0);
+
+ srand(0); //initialize random number generator
+ for (k = 0; k < p->local->process_index; k++)
+ rand();
+
+ sprintf(p->local->id, "filter_%d",
+ GETINDEX(0));
+ p->local->first_invocation = 1;
+ //generate a random filter coefficient between -1 and 1
+ p->local->filter_coefficient = ((float) (rand() % 21) - 10)/10.0;
+ p->local->zero = 0.0;
+ printf("init %s: filter coefficient = %+2.1f\n",
+ p->local->id, p->local->filter_coefficient);
+}
+
+/**
+ * Filter.
+ */
+int filter_fire(DOLProcess *p)
+{
+ //behaviour of the top filter stage
+ if (p->local->process_index == 0) {
+ if (p->local->first_invocation) {
+ DOL_read((void*)PORT_INA, &(p->local->inA), sizeof(float), p);
+ p->local->out = p->local->inA;
+ p->local->inB = 0.0;
+ p->local->first_invocation = 0;
+ }
+ else {
+ DOL_read((void*)PORT_INA, &(p->local->inA), sizeof(float), p);
+ DOL_read((void*)PORT_INB, &(p->local->inB), sizeof(float), p);
+ p->local->out = p->local->inB + p->local->inA;
+ }
+
+ DOL_write((void*)PORT_OUTA, &(p->local->out), sizeof(float), p);
+ DOL_write((void*)PORT_OUTB, &(p->local->out), sizeof(float), p);
+
+ printf("%8s: inA: %6.4f, inB: %6.4f, outA = outB: %6.4f\n",
+ p->local->id, p->local->inA, p->local->inB, p->local->out);
+ }
+ //behaviour of the intermediate filter stages
+ else {
+ if (p->local->first_invocation) {
+ DOL_read((void*)PORT_INA, &(p->local->inA), sizeof(float), p);
+ p->local->out = p->local->filter_coefficient * p->local->inA;
+ p->local->inB = 0.0;
+ p->local->first_invocation = 0;
+ }
+ else {
+ DOL_read((void*)PORT_INA, &(p->local->inA), sizeof(float), p);
+ DOL_read((void*)PORT_INB, &(p->local->inB), sizeof(float), p);
+ p->local->out = p->local->inB + p->local->filter_coefficient
+ * p->local->inA;
+ }
+
+ if (p->local->process_index < N - 1) {
+ DOL_write((void*)PORT_OUTA, &(p->local->inA), sizeof(float), p);
+ DOL_write((void*)PORT_OUTB, &(p->local->out), sizeof(float), p);
+ }
+ //behaviour of the bottom filter stage
+ else {
+ DOL_write((void*)PORT_OUTA, &(p->local->zero), sizeof(float), p);
+ DOL_write((void*)PORT_OUTB, &(p->local->out), sizeof(float), p);
+ }
+
+ printf("%8s: inA: %6.4f, inB: %6.4f, outA: %6.4f, outB: %6.4f\n",
+ p->local->id, p->local->inA, p->local->inB, p->local->inA,
+ p->local->out);
+ }
+
+ return 0;
+}
--- /dev/null
+#ifndef FILTER_H
+#define FILTER_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_INA "inA"
+#define PORT_INB "inB"
+#define PORT_OUTA "outA"
+#define PORT_OUTB "outB"
+
+typedef struct _local_states
+{
+ char id[10]; //will contain "filter_xx"
+ int first_invocation;
+ int process_index;
+ float inA, inB, out, filter_coefficient, zero;
+} Filter_State;
+
+void filter_init(DOLProcess *);
+int filter_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#define N 3
+#define NUMBER_OF_SAMPLES 5
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "producer.h"
+
+/**
+ * Returns a random integer in the range between lower_bound and
+ * upper_bound, where the bounding values are included in the interval.
+ */
+int getRandomNumber(int lower_bound, int upper_bound)
+{
+ return (rand() % (upper_bound - lower_bound + 1)) + lower_bound;
+}
+
+
+void producer_init(DOLProcess *p)
+{
+ printf("init producer.\n");
+}
+
+
+int producer_fire(DOLProcess *p)
+{
+ srand(0); //initialize random number generator
+
+ //generate input samples and display them
+ printf("producer: samples = { ");
+
+ for (p->local->index = 0; p->local->index < NUMBER_OF_SAMPLES; p->local->index++) {
+ p->local->sample[p->local->index] = (float) getRandomNumber(-9, 9);
+ if (p->local->index < NUMBER_OF_SAMPLES - 1) {
+ printf("%+3.1f, ", p->local->sample[p->local->index]);
+ }
+ else {
+ printf("%+3.1f }\n", p->local->sample[p->local->index]);
+ }
+ }
+
+ //write samples to output port
+ for (p->local->index = 0; p->local->index < NUMBER_OF_SAMPLES; p->local->index++) {
+ printf("%8s: Write sample[%02d]: %+6.4f\n",
+ "producer", p->local->index, p->local->sample[p->local->index]);
+ DOL_write((void*)PORT_OUT, &(p->local->sample[p->local->index]),
+ sizeof(float), p);
+ }
+
+ DOL_detach(p);
+ return -1;
+}
+
--- /dev/null
+#ifndef PRODUCER_H
+#define PRODUCER_H
+
+#include <dol.h>
+#include "global.h"
+#include "stdlib.h"
+
+#define PORT_OUT "out"
+
+typedef struct _local_states
+{
+ int index;
+ float sample[NUMBER_OF_SAMPLES];
+} Producer_State;
+
+void producer_init(DOLProcess *);
+int producer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<architecture xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE
+ http://www.tik.ee.ethz.ch/~shapes/schema/architecture.xsd"
+ name="Sony/Toshiba/IBM Cell Broadband Engine architecture">
+
+ <processor name="ppu" type="RISC">
+ </processor>
+
+ <processor name="spu_0" type="DSP">
+ </processor>
+
+ <processor name="spu_1" type="DSP">
+ </processor>
+
+ <processor name="spu_2" type="DSP">
+ </processor>
+
+ <processor name="spu_3" type="DSP">
+ </processor>
+
+ <processor name="spu_4" type="DSP">
+ </processor>
+
+ <processor name="spu_5" type="DSP">
+ </processor>
+
+</architecture>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<processnetwork xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK\r
+http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="example2"> \r
+\r
+ <variable value="9" name="N"/>\r
+
+\r
+ <!-- instantiate resources -->\r
+ <process name="generator">\r
+ <port type="output" name="10"/>\r
+ <source type="c" location="generator.c"/>\r
+ </process>\r
+\r
+ <iterator variable="i" range="N">\r
+ <process name="square">\r
+ <append function="i"/>\r
+ <port type="input" name="0"/>\r
+ <port type="output" name="1"/>\r
+ <source type="c" location="square.c"/>\r
+ </process>\r
+ </iterator>\r
+\r
+ <process name="consumer">\r
+ <port type="input" name="100"/>\r
+ <source type="c" location="consumer.c"/>\r
+ </process>\r
+\r
+ <iterator variable="i" range="N + 1">\r
+ <sw_channel type="fifo" size="10" name="C2">\r
+ <append function="i"/>\r
+ <port type="input" name="0"/>\r
+ <port type="output" name="1"/>\r
+ </sw_channel>\r
+ </iterator>\r
+\r
+ <!-- instantiate connection -->\r
+ <iterator variable="i" range="N">\r
+ <connection name="to_square">\r
+ <append function="i"/>\r
+ <origin name="C2">\r
+ <append function="i"/>\r
+ <port name="1"/>\r
+ </origin>\r
+ <target name="square">\r
+ <append function="i"/>\r
+ <port name="0"/>\r
+ </target>\r
+ </connection>\r
+\r
+ <connection name="from_square">\r
+ <append function="i"/>\r
+ <origin name="square">\r
+ <append function="i"/>\r
+ <port name="1"/>\r
+ </origin>\r
+ <target name="C2">\r
+ <append function="i + 1"/>\r
+ <port name="0"/>\r
+ </target>\r
+ </connection>\r
+ </iterator>\r
+\r
+ <connection name="g_">\r
+ <origin name="generator">\r
+ <port name="10"/>\r
+ </origin>\r
+ <target name="C2"> \r
+ <append function="0"/>\r
+ <port name="0"/>\r
+ </target>\r
+ </connection>\r
+\r
+ <connection name="_c">\r
+ <origin name="C2">\r
+ <append function="N"/>\r
+ <port name="1"/>\r
+ </origin>\r
+ <target name="consumer">\r
+ <port name="100"/>\r
+ </target>\r
+ </connection>\r
+\r
+</processnetwork>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<mapping xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING
+ http://www.tik.ee.ethz.ch/~shapes/schema/mapping.xsd"
+ name="examplecell on Cell">
+
+ <binding name="binding_generator" xsi:type="computation">
+ <process name="generator"/>
+ <processor name="ppu"/>
+ </binding>
+
+ <binding name="binding_square_0" xsi:type="computation">
+ <process name="square_0">
+ </process>
+ <processor name="spu_4"/>
+ </binding>
+
+ <binding name="binding_square_1" xsi:type="computation">
+ <process name="square_1">
+ </process>
+ <processor name="spu_1"/>
+ </binding>
+
+ <binding name="binding_square_2" xsi:type="computation">
+ <process name="square_2">
+ </process>
+ <processor name="spu_2"/>
+ </binding>
+
+ <binding name="binding_square_3" xsi:type="computation">
+ <process name="square_3">
+ </process>
+ <processor name="spu_3"/>
+ </binding>
+
+ <binding name="binding_square_4" xsi:type="computation">
+ <process name="square_4">
+ </process>
+ <processor name="spu_4"/>
+ </binding>
+
+ <binding name="binding_square_5" xsi:type="computation">
+ <process name="square_5">
+ </process>
+ <processor name="spu_5"/>
+ </binding>
+
+ <binding name="binding_square_6" xsi:type="computation">
+ <process name="square_6">
+ </process>
+ <processor name="spu_1"/>
+ </binding>
+
+ <binding name="binding_square_7" xsi:type="computation">
+ <process name="square_7">
+ </process>
+ <processor name="spu_2"/>
+ </binding>
+
+ <binding name="binding_square_8" xsi:type="computation">
+ <process name="square_8">
+ </process>
+ <processor name="spu_3"/>
+ </binding>
+
+ <binding name="binding_consumer" xsi:type="computation">
+ <process name="consumer"/>
+ <processor name="spu_0"/>
+ </binding>
+</mapping>
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void consumer_init(DOLProcess *p) {
+ sprintf(p->local->name, "consumer");
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int consumer_fire(DOLProcess *p) {
+ if (p->local->index < p->local->len) {
+ DOL_read((void*)PORT_IN, &p->local->c, sizeof(float), p);
+ printf("%s: %f\n", p->local->name, p->local->c);
+ p->local->index++;
+ } else {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN 100
+
+void consumer_init(DOLProcess *);
+int consumer_fire(DOLProcess *);
+
+typedef struct _local_states {
+ char name[10];
+ int index;
+ int len;
+ float c;
+} Consumer_State;
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "generator.h"
+
+void generator_init(DOLProcess *p) {
+ sprintf(p->local->name, "generator");
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int generator_fire(DOLProcess *p) {
+ if (p->local->index < p->local->len) {
+ p->local->x = (float)p->local->index;
+ DOL_write((void*)PORT_OUT, &p->local->x, sizeof(float), p);
+ p->local->index++;
+ } else {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef GENERATOR_H
+#define GENERATOR_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_OUT 10
+
+void generator_init(DOLProcess *);
+int generator_fire(DOLProcess *);
+
+typedef struct _local_states {
+ char name[10];
+ int index;
+ int len;
+ float x;
+} Generator_State;
+
+#endif
--- /dev/null
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#define LENGTH 6
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "square.h"
+
+void square_init(DOLProcess *p) {
+ sprintf(p->local->name, "square");
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int square_fire(DOLProcess *p) {
+ if (p->local->index < p->local->len) {
+ DOL_read((void*)PORT_IN, &p->local->i, sizeof(float), p);
+ p->local->i = p->local->i + p->local->i;
+ DOL_write((void*)PORT_OUT, &p->local->i, sizeof(float), p);
+ p->local->index++;
+ } else {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef SQUARE_H
+#define SQUARE_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN 0
+#define PORT_OUT 1
+
+void square_init(DOLProcess *);
+int square_fire(DOLProcess *);
+
+typedef struct _local_states {
+ char name[10];
+ int index;
+ int len;
+ float i;
+} Square_State;
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="example8">
+
+ <!-- processes -->
+ <process name="producer">
+ <port type="output" name="A"/>
+ <port type="output" name="B"/>
+ <source type="c" location="producer.c"/>
+ </process>
+
+ <process name="consumer">
+ <port type="input" name="A"/>
+ <port type="input" name="B"/>
+ <source type="c" location="consumer.c"/>
+ </process>
+
+
+ <!-- sw_channels -->
+ <sw_channel type="fifo" size="10" name="C1">
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <sw_channel type="fifo" size="10" name="C2">
+ <port type="input" name="in"/>
+ <port type="output" name="out"/>
+ </sw_channel>
+
+ <!-- connections -->
+ <connection name="p-c1-a">
+ <origin name="producer">
+ <port name="A"/>
+ </origin>
+ <target name="C1">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="p-c1-b">
+ <origin name="producer">
+ <port name="B"/>
+ </origin>
+ <target name="C2">
+ <port name="in"/>
+ </target>
+ </connection>
+
+ <connection name="c-c1-a">
+ <origin name="C1">
+ <port name="out"/>
+ </origin>
+ <target name="consumer">
+ <port name="A"/>
+ </target>
+ </connection>
+
+ <connection name="c-c2-b">
+ <origin name="C2">
+ <port name="out"/>
+ </origin>
+ <target name="consumer">
+ <port name="B"/>
+ </target>
+ </connection>
+
+</processnetwork>
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void consumer_init(DOLProcess *p) {
+ sprintf(p->local->name, "consumer");
+}
+
+int consumer_fire(DOLProcess *p) {
+ char c;
+
+ if (DOL_rtest((void*)PORT_INB, 1, p)) {
+ DOL_read((void*)PORT_INA, &c, sizeof(char), p);
+ printf("from port B: %c\n", c);
+ DOL_read((void*)PORT_INA, &c, sizeof(char), p);
+ printf("from port A: %c\n", c);
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+
+#define PORT_INA "A"
+#define PORT_INB "B"
+
+typedef struct _local_states {
+ char name[10];
+} Consumer_State;
+
+void consumer_init(DOLProcess *);
+int consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "producer.h"
+
+// initialization function
+void producer_init(DOLProcess *p) {
+ p->local->index = 0;
+ p->local->len = 20;
+ sprintf(p->local->str, "abcdefghijklmnopqrstuvwxyz");
+
+}
+
+int producer_fire(DOLProcess *p) {
+
+ if (p->local->index < p->local->len) {
+ if (DOL_wtest((void*)PORT_OUTA, 1, p)) {
+ DOL_write((void*)PORT_OUTA, &(p->local->str[p->local->index]),
+ 1, p);
+ printf("p write to port A %c\n",
+ p->local->str[p->local->index]);
+ }
+ else {
+ DOL_write((void*)PORT_OUTB, &(p->local->str[p->local->index]),
+ 1, p);
+ printf("p write to port B %c\n",
+ p->local->str[p->local->index]);
+ }
+ p->local->index++;
+ return 0;
+ }
+ else {
+ DOL_detach(p);
+ return -1;
+ }
+}
+
--- /dev/null
+#ifndef PRODUCER_H
+#define PRODUCER_H
+
+#include <dol.h>
+
+#define PORT_OUTA "A"
+#define PORT_OUTB "B"
+
+typedef struct _local_states {
+ int index;
+ int len;
+ char str[26];
+} Producer_State;
+
+void producer_init(DOLProcess *);
+int producer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork
+xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+ http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="independent processes">
+
+ <!-- processes -->
+ <iterator variable="i" range="3">
+ <process name="task">
+ <append function="i"/>
+ <source type="c" location="task.c"/>
+ </process>
+ </iterator>
+
+</processnetwork>
--- /dev/null
+#include <stdio.h>
+
+#include "task.h"
+
+void task_init(DOLProcess *p) {
+ sprintf(p->local->name, "task_%d", GETINDEX(0));
+ p->local->index = 0;
+}
+
+int task_fire(DOLProcess *p) {
+ if (p->local->index < 10) {
+ printf("%s: %d\n", p->local->name, p->local->index++);
+ }
+
+ if (p->local->index >= 10) {
+ DOL_detach(p);
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef TASK_H
+#define TASK_H
+
+#include <dol.h>
+
+typedef struct _local_states {
+ char name[10];
+ int index;
+ int len;
+} Task_State;
+
+void task_init(DOLProcess *);
+int task_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<processnetwork
+xmlns="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK
+ http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd" name="examplewindowedfifo">
+
+ <!-- processes -->
+ <process name="generator">
+ <port type="output" name="1"/>
+ <source type="c" location="generator.c"/>
+ <configuration name="triggerPeriod" value="100000"/>
+ </process>
+
+ <process name="consumer">
+ <port type="input" name="1"/>
+ <source type="c" location="consumer.c"/>
+ </process>
+
+ <process name="square">
+ <port type="input" name="100"/>
+ <port type="output" name="200"/>
+ <source type="c" location="square.c"/>
+ </process>
+
+ <!-- sw_channels -->
+ <sw_channel type="wfifo" size="12" name="C1">
+ <port type="input" name="0"/>
+ <port type="output" name="1"/>
+ </sw_channel>
+
+ <sw_channel type="wfifo" size="12" name="C2">
+ <port type="input" name="0"/>
+ <port type="output" name="1"/>
+ </sw_channel>
+
+ <!-- connections -->
+ <connection name="g-c">
+ <origin name="generator">
+ <port name="1"/>
+ </origin>
+ <target name="C1">
+ <port name="0"/>
+ </target>
+ </connection>
+
+ <connection name="c-c">
+ <origin name="C2">
+ <port name="1"/>
+ </origin>
+ <target name="consumer">
+ <port name="1"/>
+ </target>
+ </connection>
+
+ <connection name="s-c">
+ <origin name="square">
+ <port name="200"/>
+ </origin>
+ <target name="C2">
+ <port name="0"/>
+ </target>
+ </connection>
+
+ <connection name="c-s">
+ <origin name="C1">
+ <port name="1"/>
+ </origin>
+ <target name="square">
+ <port name="100"/>
+ </target>
+ </connection>
+
+</processnetwork>
--- /dev/null
+#include <stdio.h>
+
+#include "consumer.h"
+
+void consumer_init(DOLProcess *p) {
+ sprintf(p->local->name, "consumer");
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int consumer_fire(DOLProcess *p) {
+ float *c;
+ if (p->local->index < p->local->len) {
+ DOL_capture((void*)PORT_IN, &c, sizeof(float), p);
+ printf("%s: %f\n", p->local->name, *c);
+ DOL_consume((void*)PORT_IN, p);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef CONSUMER_H
+#define CONSUMER_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN 1
+
+typedef struct _local_states {
+ char name[10];
+ int index;
+ int len;
+} Consumer_State;
+
+void consumer_init(DOLProcess *);
+int consumer_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#include "generator.h"
+
+// initialization function
+void generator_init(DOLProcess *p) {
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int generator_fire(DOLProcess *p) {
+
+ if (p->local->index < p->local->len) {
+ float *x;
+ DOL_reserve((void*)PORT_OUT, &x, sizeof(float), p);
+ *x = (float)p->local->index;
+ DOL_release((void*)PORT_OUT, p);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef GENERATOR_H
+#define GENERATOR_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_OUT 1
+
+typedef struct _local_states {
+ int index;
+ int len;
+} Generator_State;
+
+void generator_init(DOLProcess *);
+int generator_fire(DOLProcess *);
+
+#endif
--- /dev/null
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#define LENGTH 20
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "square.h"
+
+void square_init(DOLProcess *p) {
+ p->local->index = 0;
+ p->local->len = LENGTH;
+}
+
+int square_fire(DOLProcess *p) {
+ float *i, *j;
+
+ if (p->local->index < p->local->len) {
+ DOL_capture((void*)PORT_IN, &i, sizeof(float), p);
+ DOL_reserve((void*)PORT_OUT, &j, sizeof(float), p);
+ *j = *i * *i;
+ DOL_consume((void*)PORT_IN, p);
+ DOL_release((void*)PORT_OUT, p);
+ p->local->index++;
+ }
+
+ if (p->local->index >= p->local->len) {
+ DOL_detach(p);
+ return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+#ifndef SQUARE_H
+#define SQUARE_H
+
+#include <dol.h>
+#include "global.h"
+
+#define PORT_IN 100
+#define PORT_OUT 200
+
+typedef struct _local_states {
+ int index;
+ int len;
+} Square_State;
+
+void square_init(DOLProcess *);
+int square_fire(DOLProcess *);
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="dol" default="runexample" basedir=".">
+
+ <description>
+ Ant build file to build and run examples.
+ </description>
+
+ <!-- java compiler properties: a java compiler for Java Platform 5.0 is required -->
+ <!-- do _not_ comment out the following line to use the specified external java compiler and virtual machine -->
+ <!-- <property name="use.external.java" value="yes"/> -->
+ <!-- <property name="use.external.javac" value="yes"/> -->
+
+ <!-- external java binaries -->
+ <property name="java.executable" value="/usr/sepp/bin/java"/>
+ <property name="javac.executable" value="/usr/sepp/bin/javac"/>
+
+ <!-- directory paths -->
+ <property name="lib.dir" location="./../../../jars"/>
+ <property name="bin.dir" location="./../../../bin"/>
+ <property name="jars" value=".:./..:${lib.dir}/dol.jar:${lib.dir}/xercesImpl.jar:${lib.dir}/jdom.jar:${bin.dir}/dol.jar:${bin.dir}/xercesImpl.jar:${bin.dir}/jdom.jar"/>
+ <property name="example.dir" location="./../../../examples"/>
+
+ <!-- these properties can be overwritten using the -D option when calling ant, e.g.: -Dnumber=2 -Dgenerator=protothread -->
+ <property name="number" value="1"/>
+ <property name="generator" value="HdS"/> <!-- HdS, protothread, systemC, PaF, rtems, yapi -->
+
+
+ <!-- main target: calls all the targets required to run an example -->
+ <target name="runexample" depends="showversion">
+ <antcall target="prepare"/>
+ <antcall target="validate"/>
+ <antcall target="flatten1"/>
+ <antcall target="flatten2"/>
+ <antcall target="dol1"/>
+ <antcall target="dol2"/>
+ <antcall target="execute"/>
+ </target>
+
+ <target name="mparm" depends="showversion">
+ <antcall target="prepare"/>
+ <antcall target="validate"/>
+ <antcall target="flatten1"/>
+ <antcall target="flatten2"/>
+ <antcall target="dol_mparm1"/>
+ <antcall target="dol_mparm2"/>
+ </target>
+
+ <target name="cell" depends="showversion">
+ <antcall target="prepare"/>
+ <antcall target="validate"/>
+ <antcall target="flatten1"/>
+ <antcall target="flatten2"/>
+ <antcall target="dol_cell1"/>
+ <antcall target="dol_cell2"/>
+ </target>
+
+ <!-- prepare directory structure and copy sources -->
+ <target name="prepare">
+ <echo message="Create directory example${number}."/>
+ <deletedirectory dir="example${number}"/>
+ <mkdir dir="example${number}"/>
+
+ <echo message="Copy C source files."/>
+ <deletedirectory dir="example${number}/src"/>
+ <mkdir dir="example${number}/src"/>
+ <copy todir="example${number}/src">
+ <fileset dir="${example.dir}/example${number}/src" includes="*.h *.c"/>
+ </copy>
+ </target>
+
+ <!-- validateXML by means of external schema -->
+ <target name="validate" unless="use.external.java">
+ <echo message="check XML compliance of example${number}_flattened.xml."/>
+ <java classname="dol.helper.validator.XMLValidator"
+ dir="example${number}"
+ fork="true"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="${example.dir}/example${number}/example${number}.xml"/>
+ </java>
+ </target>
+
+ <!-- create flattened XML (non-external java version) -->
+ <target name="flatten1" unless="use.external.java">
+ <echo message="Create flattened XML example${number}_flattened.xml."/>
+ <java classname="dol.helper.flattener.XMLFlattener"
+ dir="example${number}"
+ fork="true"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="${example.dir}/example${number}/example${number}.xml Example${number}Generator"/>
+ </java>
+
+ <javac srcdir="example${number}"
+ destdir="example${number}"
+ includes="Example${number}Generator.java"
+ fork="${use.external.javac}"
+ executable="${javac.executable}"/>
+
+ <java classname="Example${number}Generator"
+ output="example${number}/example${number}_flattened.xml"
+ fork="true"
+ failonerror="true">
+ <classpath path="example${number}"/>
+ </java>
+ </target>
+
+ <!-- create flattened XML (external java version) -->
+ <target name="flatten2" if="use.external.java">
+ <echo message="Create flattened XML example${number}_flattened.xml."/>
+ <java classname="dol.helper.flattener.XMLFlattener"
+ dir="example${number}"
+ fork="true"
+ jvm="${java.executable}"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="${example.dir}/example${number}/example${number}.xml Example${number}Generator"/>
+ </java>
+
+ <javac srcdir="example${number}"
+ destdir="example${number}"
+ includes="Example${number}Generator.java"
+ fork="${use.external.javac}"
+ executable="${javac.executable}"/>
+
+ <java classname="Example${number}Generator"
+ output="example${number}/example${number}_flattened.xml"
+ fork="true"
+ jvm="${java.executable}"
+ failonerror="true">
+ <classpath path="example${number}"/>
+ </java>
+ </target>
+
+ <!-- run DOL (non-external java version) -->
+ <target name="dol1" unless="use.external.java">
+ <echo message="Run DOL."/>
+ <java classname="dol.main.Main"
+ dir="example${number}"
+ fork="true"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="-P example${number}_flattened.xml -D example${number}.dot --${generator} ${generator} -c"/>
+ </java>
+ </target>
+
+ <target name="dol_mparm1" unless="use.external.java">
+ <echo message="Run mparm generation."/>
+ <java classname="dol.main.Main"
+ dir="example${number}"
+ fork="true"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="-P example${number}_flattened.xml -D example${number}.dot -Rmparm mparm -c"/>
+ </java>
+ </target>
+
+ <target name="dol_cell1" unless="use.external.java">
+ <echo message="Run cell generation."/>
+ <java classname="dol.main.Main"
+ dir="example${number}"
+ fork="true"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="-P example${number}_flattened.xml -D example${number}.dot --cbe cell --platform ./../../../../examples/example${number}/cell.xml --mapping ./../../../../examples/example${number}/mapping.xml -c"/>
+ </java>
+ </target>
+
+ <!-- run DOL (external java version) -->
+ <target name="dol2" if="use.external.java">
+ <echo message="Run DOL."/>
+ <java classname="dol.main.Main"
+ dir="example${number}"
+ fork="true"
+ jvm="${java.executable}"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="-P example${number}_flattened.xml -D example${number}.dot --${generator} ${generator} -c"/>
+ </java>
+ </target>
+
+ <target name="dol_mparm2" if="use.external.java">
+ <echo message="Run mparm generation."/>
+ <java classname="dol.main.Main"
+ dir="example${number}"
+ fork="true"
+ jvm="${java.executable}"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="-P example${number}_flattened.xml -D example${number}.dot -Rmparm mparm -c"/>
+ </java>
+ </target>
+
+ <target name="dol_cell2" if="use.external.java">
+ <echo message="Run cell generation."/>
+ <java classname="dol.main.Main"
+ dir="example${number}"
+ fork="true"
+ jvm="${java.executable}"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="-P example${number}_flattened.xml -D example${number}.dot --cbe cell --platform cell.xml --mapping mapping.xml -c"/>
+ </java>
+ </target>
+
+
+ <!-- create and run SystemC application -->
+ <target name="execute">
+ <!-- the first two tasks are needed to avoid make's clock skew warning -->
+ <tstamp>
+ <format property="touch.time"
+ pattern="MM/dd/yyyy hh:mm aa"
+ offset="-5" unit="second"/>
+ </tstamp>
+ <touch datetime="${touch.time}">
+ <fileset dir="example${number}"/>
+ </touch>
+
+ <echo message="Make ${generator} application."/>
+ <exec executable="make" dir="example${number}/${generator}/src"/>
+
+ <echo message="Run ${generator} application."/>
+ <exec executable="${basedir}/example${number}/${generator}/src/sc_application"
+ output="example${number}/${generator}/src/log.txt"
+ error="example${number}/${generator}/src/errorlog.txt"/>
+ <concat>
+ <fileset dir="example${number}/${generator}/src" includes="log.txt"/>
+ </concat>
+ </target>
+
+ <!-- run the XML checker -->
+ <target name="checkxmls">
+ <java classname="dol.util.CheckXMLs" failonerror="true" fork="true">
+ <classpath path="${jars}"/>
+ <arg line="${example.dir}/examplecell/examplecell.xml ${example.dir}/examplecell/cell.xml ${example.dir}/examplecell/mapping.xml"/>
+ </java>
+ </target>
+
+ <!-- run the application generator -->
+ <target name="applicationgenerator">
+ <java classname="dol.util.ApplicationGenerator" failonerror="true" fork="true">
+ <classpath path="${jars}"/>
+ </java>
+ </target>
+
+ <!-- recursively delete a directory -->
+ <macrodef name="deletedirectory">
+ <attribute name="dir"/>
+ <sequential>
+ <delete includeemptydirs="true" quiet="true">
+ <fileset dir="${dir}" includes="**/*"/>
+ </delete>
+ </sequential>
+ </macrodef>
+
+ <target name="showversion">
+ <antcall target="showantversion"/>
+ <antcall target="showjavaversion1"/>
+ <antcall target="showjavaversion2"/>
+ <antcall target="showjavacversion1"/>
+ <antcall target="showjavacversion2"/>
+ </target>
+
+ <target name="showantversion">
+ <echo message="Use ${ant.version}."/>
+ </target>
+
+ <target name="showjavacversion1" unless="use.external.javac">
+ <echo message="Use Java version ${java.version} (required version: 1.5.0 or higher)."/>
+ </target>
+
+ <target name="showjavacversion2" if="use.external.javac">
+ <echo message="Use the following javac: ${javac.executable}."/>
+ </target>
+
+ <target name="showjavaversion1" unless="use.external.java">
+ <echo message="Use Java version ${java.version} (required version: 1.5.0 or higher)."/>
+ </target>
+
+ <target name="showjavaversion2" if="use.external.java">
+ <echo message="Use the following java: ${java.executable}."/>
+ </target>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="runprofiler" default="run" basedir=".">
+
+ <!-- *************************************************************** -->
+ <!-- * properties * -->
+ <!-- *************************************************************** -->
+
+ <!-- modify the following properties as required -->
+
+ <!-- directory where DOL is located (needed for reading processnetwork from XML file-->
+ <property name="lib.dir" location="./../../../jars"/>
+ <property name="bin.dir" location="./../../../bin"/>
+ <property name="jars" value=".:./..:${lib.dir}/dol.jar:${lib.dir}/xercesImpl.jar:${lib.dir}/jdom.jar:${bin.dir}/dol.jar:${bin.dir}/xercesImpl.jar:${bin.dir}/jdom.jar"/>
+
+ <!-- classpath delimiter ":" for UNIX, ";" for Windows -->
+ <property name="classpathdelimiter" value=":"/>
+
+ <!-- this can be overwritten using the -D option to ant, e.g.: -Dnumber=2 -->
+ <property name="number" value="1"/>
+
+ <!-- *************************************************************** -->
+ <!-- * targets * -->
+ <!-- *************************************************************** -->
+ <target name="arch">
+ <java classname="dol.main.Main"
+ classpath="${jars}">
+ <arg line=" -p ../../../examples/arch/vsp.xml"/>
+ </java>
+ </target>
+
+ <target name="run">
+ <java classname="dol.main.Main"
+ classpath="${jars}">
+ <arg line=" -T profile.txt -P example${number}/example${number}_flattened.xml -G example${number}/example${number}_flattened_annotated.xml"/>
+ </java>
+ </target>
+
+ <target name="standalone">
+ <java classname="dol.helper.profiler.Profiler"
+ classpath="${jars}">
+ <arg line=" profile.txt example${number}/example${number}_flattened.xml"/>
+ </java>
+ </target>
+</project>
--- /dev/null
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:arch="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE" targetNamespace="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE" elementFormDefault="qualified">
+ <xsd:include schemaLocation="generics.xsd"/>
+
+ <xsd:element name="architecture">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="variable" type="arch:variable" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="function" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="processor" type="arch:processor" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="memory" type="arch:memory" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="hw_channel" type="arch:hw_channel" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="iterator" type="arch:generaliterator" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="readpath" type="arch:readpath" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="writepath" type="arch:writepath" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="processor">
+ <xsd:complexContent>
+ <xsd:extension base="arch:resource">
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="RISC"/>
+ <xsd:enumeration value="DSP"/>
+ <xsd:enumeration value="POT"/>
+ <xsd:enumeration value="NETSIM"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="memory">
+ <xsd:complexContent>
+ <xsd:extension base="arch:resource">
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="ROM"/>
+ <xsd:enumeration value="RAM"/>
+ <xsd:enumeration value="REG"/>
+ <xsd:enumeration value="DXM"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="hw_channel">
+ <xsd:complexContent>
+ <xsd:extension base="arch:resource">
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="FIFO"/>
+ <xsd:enumeration value="BUS"/>
+ <xsd:enumeration value="DMA"/>
+ <xsd:enumeration value="SPI"/>
+ <xsd:enumeration value="BRIDGE"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="resource">
+ <xsd:complexContent>
+ <xsd:extension base="arch:element">
+ <xsd:sequence>
+ <xsd:element name="append" type="arch:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="configuration" type="arch:configuration" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="writepath">
+ <xsd:sequence minOccurs="1" maxOccurs="1">
+ <xsd:element name="append" type="arch:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="processor" type="arch:resourcereference" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="txbuf" type="arch:resourcereference" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="hw_channel" type="arch:resourcereference" minOccurs="1" maxOccurs="unbounded"/>
+ <xsd:element name="chbuf" type="arch:resourcereference" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="configuration" type="arch:configuration" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="readpath">
+ <xsd:sequence minOccurs="1" maxOccurs="1">
+ <xsd:element name="append" type="arch:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="processor" type="arch:resourcereference" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="chbuf" type="arch:resourcereference" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="hw_channel" type="arch:resourcereference" minOccurs="1" maxOccurs="unbounded"/>
+ <xsd:element name="rxbuf" type="arch:resourcereference" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="configuration" type="arch:configuration" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="resourcereference">
+ <xsd:sequence>
+ <xsd:element name="append" type="arch:append" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="generaliterator">
+ <xsd:complexContent>
+ <xsd:extension base="arch:iterator">
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="readpath" type="arch:readpath" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="writepath" type="arch:writepath" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="processor" type="arch:processor" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="memory" type="arch:memory" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="hw_channel" type="arch:hw_channel" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="iterator" type="arch:generaliterator" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+</xsd:schema>
--- /dev/null
+#!/bin/bash
+
+##########################################################################
+# Script to collect together processnetwork.xsd, architecture.xsd, and
+# mapping.xsd into a single LaTeX document.
+#
+# Lines longer than 80 characters in the source files are truncated.
+#
+# modification history:
+# 2006-08-22: created
+#
+##########################################################################
+
+##########################################################################
+# create LaTeX header
+##########################################################################
+
+echo -e %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'\n'\
+% XML Schema Definitions.'\n'\
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'\n'\
+'\n'\
+'\\'documentclass[11pt,oneside]{book}'\n'\
+'\\'usepackage{fancyhdr,ifthen,a4wide,textcomp,version,amsmath,bbm,url}'\n'\
+'\\'usepackage[latin1]{inputenc}'\n'\
+'\n'\
+%package for including listings'\n'\
+'\\'usepackage{listings}'\n'\
+'\\'lstset{basicstyle='\\'small, xleftmargin=12pt, numbersep=12pt, numbers=left,'\n'\
+ numberstyle='\\'tiny, numbersep=5pt}'\n'\
+%print two-digit line numbers'\n'\
+'\\'newcommand{'\\'twodig}[1]'\n'\
+ {'\\'ifcase#1 00'\\'or01'\\'or02'\\'or03'\\'or04'\\'or05'\\'or06'\\'or07'\\'or08'\\'or09'\\'else#1'\\'fi}'\n'\
+'\\'renewcommand{'\\'thelstnumber}{'\\'twodig{'\\'arabic{lstnumber}}}'\n'\
+'\n'\
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'\n'\
+%page layout and graphics path'\n'\
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'\n'\
+'\\'setlength{'\\'textwidth}{18 true cm}'\n'\
+'\\'setlength{'\\'textheight}{27.4 true cm}'\n'\
+'\\'oddsidemargin -1.0 cm'\n'\
+'\\'evensidemargin -1.0 cm'\n'\
+'\\'topmargin -2.4 cm'\n'\
+'\\'setlength{'\\'parindent}{0pt}'\n'\
+'\\'sloppy'\n'\
+'\\'flushbottom'\n'\
+'\\'pagestyle{empty}'\n'\
+'\n'\
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'\n'\
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'\n'\
+'\n'\
+'\\'begin{document} > latex_header.tex
+
+
+##########################################################################
+# create LaTeX footer
+##########################################################################
+
+echo -e '\\'end{document} > latex_footer.tex
+
+
+##########################################################################
+# create listings header and footer
+##########################################################################
+
+echo -e '\\'newpage'\n'\
+'\\'begin{lstlisting} > listing_header.tex
+
+echo -e '\\'end{lstlisting} > listing_footer.tex
+
+
+##########################################################################
+# create document
+##########################################################################
+
+cat latex_header.tex listing_header.tex processnetwork.xsd listing_footer.tex \
+ listing_header.tex architecture.xsd listing_footer.tex \
+ listing_header.tex mapping.xsd listing_footer.tex latex_footer.tex > schemas.tex
+
+
+##########################################################################
+# truncate lines longer than 80 characters
+##########################################################################
+
+sed -i 's/\(^.\{80\}\).*/\1.../g' schemas.tex
+
+
+##########################################################################
+# remove help files
+##########################################################################
+
+rm -f latex_header.tex latex_footer.tex listing_header.tex listing_footer.tex
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+ <xsd:complexType name="variable">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="value" type="xsd:integer" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="function">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="name" type="xsd:string" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="append">
+ <xsd:attribute name="function" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="iterator">
+ <xsd:attribute name="variable" type="xsd:string" use="required"/>
+ <xsd:attribute name="range" type="xsd:string" use="required"/>
+ <!--
+ <xsd:attribute name="range" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="for.*"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ -->
+ </xsd:complexType>
+
+ <xsd:complexType name="configuration">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="value" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="profiling">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="value" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="element">
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="basename" type="xsd:string" use="optional"/>
+ <xsd:attribute name="range" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+
+</xsd:schema>
--- /dev/null
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:arch="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE" targetNamespace="http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE" elementFormDefault="qualified">
+ <xsd:include schemaLocation="../architecture.xsd"/>
+</xsd:schema>
--- /dev/null
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:arch="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING" targetNamespace="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING" elementFormDefault="qualified">
+ <xsd:include schemaLocation="../mapping.xsd"/>
+</xsd:schema>
--- /dev/null
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pn="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" targetNamespace="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" elementFormDefault="qualified">
+
+<xsd:redefine schemaLocation="../processnetwork.xsd">
+ <xsd:complexType name="process">
+ <xsd:complexContent>
+ <xsd:extension base="pn:process">
+ <xsd:sequence>
+ <xsd:element name="profiling" type="pn:profiling" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="sw_channel">
+ <xsd:complexContent>
+ <xsd:extension base="pn:sw_channel">
+ <xsd:sequence>
+ <xsd:element name="profiling" type="pn:profiling" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+</xsd:redefine>
+
+</xsd:schema>
--- /dev/null
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:map="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING" targetNamespace="http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING" elementFormDefault="qualified">
+ <xsd:include schemaLocation="generics.xsd"/>
+
+ <xsd:element name="mapping">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="variable" type="map:variable" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="function" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="iterator" type="map:generaliterator" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="binding" type="map:binding" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="schedule" type="map:schedule" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="binding">
+ <xsd:sequence>
+ <xsd:element name="append" type="map:append" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="computation">
+ <xsd:complexContent>
+ <xsd:extension base="map:binding">
+ <xsd:sequence>
+ <xsd:element name="process" type="map:resource" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="processor" type="map:resource" minOccurs="1" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="communication">
+ <xsd:complexContent>
+ <xsd:extension base="map:binding">
+ <xsd:sequence>
+ <xsd:element name="sw_channel" type="map:resource" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="writepath" type="map:resource" minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="readpath" type="map:resource" minOccurs="1" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="schedule">
+ <xsd:sequence>
+ <xsd:element name="append" type="map:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="resource" type="map:resource"/>
+ <xsd:element name="origin" type="map:configuredresource" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="configuration" type="map:configuration" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="static"/>
+ <xsd:enumeration value="fixedpriority"/>
+ <xsd:enumeration value="fifo"/>
+ <xsd:enumeration value="tdma"/>
+ <xsd:enumeration value="roundrobin"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:complexType>
+
+ <xsd:complexType name="resource">
+ <xsd:sequence>
+ <xsd:element name="append" type="map:append" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="configuredresource">
+ <xsd:sequence>
+ <xsd:element name="append" type="map:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="configuration" type="map:configuration" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="generaliterator">
+ <xsd:complexContent>
+ <xsd:extension base="map:iterator">
+ <xsd:sequence>
+ <xsd:element name="iterator" type="map:generaliterator" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="binding" type="map:binding" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="schedule" type="map:schedule" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+</xsd:schema>
--- /dev/null
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pn="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" targetNamespace="http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK" elementFormDefault="qualified" >
+ <xsd:include schemaLocation="generics.xsd"/>
+
+ <xsd:element name="processnetwork">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="variable" type="pn:variable" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="function" type="pn:function" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="process" type="pn:process" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="sw_channel" type="pn:sw_channel" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="iterator" type="pn:generaliterator" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="connection" type="pn:connection" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="configuration" type="pn:configuration" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="process">
+ <xsd:complexContent>
+ <xsd:extension base="pn:element">
+ <xsd:sequence>
+ <xsd:element name="append" type="pn:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:choice minOccurs="0">
+ <xsd:sequence>
+ <xsd:element name="iterator" type="pn:qualifiedportiterator" maxOccurs="unbounded"/>
+ <xsd:element name="port" type="pn:qualifiedport" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:element name="port" type="pn:qualifiedport" maxOccurs="unbounded"/>
+ </xsd:choice>
+ <xsd:element name="source" type="pn:source"/>
+ <xsd:element name="configuration" type="pn:configuration" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="source">
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="c"/>
+ <xsd:enumeration value="c++"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="location" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="sw_channel">
+ <xsd:complexContent>
+ <xsd:extension base="pn:element">
+ <xsd:sequence>
+ <xsd:element name="append" type="pn:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="port" type="pn:qualifiedport" minOccurs="2" maxOccurs="2"/>
+ <xsd:element name="configuration" type="pn:configuration" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="size" type="xsd:string" use="required"/>
+ <xsd:attribute name="tokensize" type="xsd:string" default="1" use="optional"/>
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="fifo"/>
+ <xsd:enumeration value="wfifo"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="port">
+ <xsd:complexContent>
+ <xsd:extension base="pn:element">
+ <xsd:sequence>
+ <xsd:element name="append" type="pn:append" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="qualifiedport">
+ <xsd:complexContent>
+ <xsd:extension base="pn:port">
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="input"/>
+ <xsd:enumeration value="output"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="connection">
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="append" type="pn:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="origin" type="pn:connector"/>
+ <xsd:element name="target" type="pn:connector"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="connector">
+ <xsd:sequence>
+ <xsd:element name="append" type="pn:append" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="port" type="pn:port"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="generaliterator">
+ <xsd:complexContent>
+ <xsd:extension base="pn:iterator">
+ <xsd:sequence>
+ <xsd:element name="iterator" type="pn:generaliterator" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="process" type="pn:process" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="sw_channel" type="pn:sw_channel" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="connection" type="pn:connection" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="qualifiedportiterator">
+ <xsd:complexContent>
+ <xsd:extension base="pn:iterator">
+ <xsd:choice>
+ <xsd:sequence>
+ <xsd:element name="iterator" type="pn:qualifiedportiterator" maxOccurs="unbounded"/>
+ <xsd:element name="port" type="pn:qualifiedport" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:element name="port" type="pn:qualifiedport" maxOccurs="unbounded"/>
+ </xsd:choice>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+</xsd:schema>
--- /dev/null
+Manifest-Version: 1.0\r
+Main-Class: dol.main.Main\r
+Created-By: Computer Engineering Group, Computer Engineering and Networks Laboratory, ETH Zurich\r
+Class-Path: jars/xercesImpl.jar jars/jdom.jar
\ No newline at end of file
--- /dev/null
+# Doxyfile 1.3.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = DOL
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 1.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ../../../build/doxygen/
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
+# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese,
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH = ../../src
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = YES
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../../dol
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
+
+FILE_PATTERNS = *.java
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 1
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+#HTML_HEADER = header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+#HTML_FOOTER = footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output dir.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similiar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH = /usr/local/bin/dot
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 600
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 600
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = YES
--- /dev/null
+<hr/>
+<p class="small">Generated on $datetime for $projectname by <a href="http://www.doxygen.org/index.html">doxygen</a> $doxygenversion</p>
+<!-- <?php include("/home/khuang/footer.php"); ?> -->
--- /dev/null
+<?php $nonvalidhtml=true; $mytitle="developer reference"; ?>
--- /dev/null
+# template for dol.properties file
+# use ant config to fill in the values
+
+# SystemC library path:
+# SYSTEMC_INC and SYSTEMC_LIB are the paths to SystemC header and library,
+# respectively. These two path will be used in the generated Makefile to
+# build the SystemC executable binary file. They have to point to local
+# SystemC directory.
+#
+# example:
+# SYSTEMC_INC = /home/shapes/base/resources/lib/systemC/systemc-2.1.v1/include
+# SYSTEMC_LIB = /home/shapes/base/resources/lib/systemC/systemc-2.1.v1/lib-linux/libsystemc.a
+
+SYSTEMC_INC = /home/shapes/base/resources/lib/systemC/include
+SYSTEMC_LIB = /home/shapes/base/resources/lib/systemC/lib-linux/libsystemc.a
--- /dev/null
+/* $Id: SanityCheck.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.check;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+
+import dol.datamodel.architecture.ArchiResource;
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.architecture.Configuration;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Connection;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.Resource;
+
+/**
+ * Check semantic correctness of process network.
+ *
+ * This class checks
+ * <ul><li>whether it is a processnetwork</li>
+ * <li>a channel only has two ports</li>
+ * <li>each channel port has only one peer port of process</li>
+ * </ul>
+ */
+public class SanityCheck {
+ /**
+ * Return the singleton instance of this class;
+ *
+ * @return the instance.
+ */
+ public final static SanityCheck getInstance() {
+ return _instance;
+ }
+
+ /**
+ * Check if the process network spec is correct
+ *
+ * @param pn processnetwork to check
+ */
+ public void checkPN(ProcessNetwork pn) {
+ try {
+ _checkNameConflict(pn);
+ _checkChannelPorts(pn);
+ _checkChannelConnection(pn);
+ }
+ catch (Exception e) {
+ System.out.println("err: " + e.getMessage());
+ //e.printStackTrace();
+ System.exit(-1);
+ }
+
+ try {
+ _checkProcessConnection(pn);
+ }
+ catch (Exception e) {
+ System.out.println("warning: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Check if the architecture spec is correct
+ *
+ * @param arch architecture to check
+ */
+ public void checkArch(Architecture arch)
+ {
+ try
+ {
+ _checkNameConflict(arch);
+ _checkNETSIM(arch);
+ _checkMaster(arch);
+ }
+ catch (Exception e)
+ {
+ System.out.println("err: " + e.getMessage());
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * Check if the mapping spec is correct
+ *
+ * @param map mapping to check
+ */
+ public void checkMap(Mapping map)
+ {
+ try
+ {
+ _checkMultibind(map);
+ _checkProcessesBound(map);
+ }
+ catch (Exception e)
+ {
+ System.out.println("err: " + e.getMessage());
+ System.exit(-1);
+ }
+ }
+
+
+ /**
+ * Check name exclusiveness, including processes, channels, and
+ * connections.
+ *
+ * @param pn processnetwork to check
+ */
+ private void _checkNameConflict(ProcessNetwork pn) throws Exception {
+ System.out.println("APPL: Checking resource name ...");
+
+ Vector<Resource> n = new Vector<Resource>(pn.getChannelList());
+ n.addAll(pn.getProcessList());
+ n.addAll(pn.getConnectionList());
+
+ //sort resources in n by name
+ Collections.sort(n,
+ new Comparator<Resource>()
+ {
+ public int compare(Resource resource1, Resource resource2) {
+ return resource1.getName().compareTo(resource2.getName());
+ }
+ } );
+
+ //test adjacent resources in n for equal name
+ for (int k = 0; k < n.size() - 1; k++)
+ {
+ if (((Resource) n.elementAt(k)).getName().equals(
+ ((Resource) n.elementAt(k + 1)).getName())) {
+ throw new Exception("Name conflict: " +
+ ((Resource)n.elementAt(k + 1)).getName() +
+ " appears (at least) twice.");
+ }
+ }
+ }
+
+ /**
+ * Check number of ports for every channel.
+ *
+ * @param pn processnetwork to check
+ */
+ private void _checkChannelPorts(ProcessNetwork pn) throws Exception {
+ System.out.println("APPL: Checking channel ports ...");
+
+ for (Channel c : pn.getChannelList()) {
+ if (c.getPortList().size() < 2) {
+ throw new Exception("channel ports less than 2: " +
+ c.getName());
+ }
+ }
+ }
+
+ /**
+ * Check whether all processes are connected.
+ *
+ * @param pn processnetwork to check
+ */
+ private void _checkProcessConnection(ProcessNetwork pn)
+ throws Exception {
+ System.out.println("APPL: Checking Process connection ...");
+
+ String result = "";
+ boolean hasUnused = false;
+ for (Process r : pn.getProcessList()) {
+ boolean flag = false;
+ for (Connection c : pn.getConnectionList()) {
+ Resource origin = c.getOrigin();
+ Resource target = c.getTarget();
+ if (r.getName().equals(origin.getName())) {
+ flag = true; break;
+ } else if (r.getName().equals(target.getName())) {
+ flag = true; break;
+ }
+ }
+ if (flag == false) {
+ hasUnused = true;
+ result += " " + r.getName();
+ }
+ }
+
+ if (hasUnused == true)
+ throw new Exception("process(es) without connection to channels:" + result);
+ }
+
+ /**
+ * Check whether there are unused channels in the processnetwork.
+ *
+ * @param pn processnetwork to check
+ */
+ private void _checkChannelConnection(ProcessNetwork pn)
+ throws Exception {
+ System.out.println("APPL: Checking channel connection ...");
+
+ String result = "";
+ boolean hasUnused = false;
+ for (Channel r : pn.getChannelList()) {
+ boolean flag = false;
+ for (Connection c: pn.getConnectionList()) {
+ Resource origin = c.getOrigin();
+ Resource target = c.getTarget();
+ if (r.getName().equals(origin.getName())) {
+ flag = true; break;
+ } else if (r.getName().equals(target.getName())) {
+ flag = true; break;
+ }
+ }
+ if (flag == false) {
+ hasUnused = true;
+ result += " " + r.getName();
+ }
+ }
+
+ if (hasUnused == true)
+ throw new Exception("unused channel: " + result);
+ }
+
+
+ /**
+ * Check name exclusiveness, including both processors and memories.
+ *
+ * @param arch architecture to check
+ */
+ private void _checkNameConflict(Architecture arch) throws Exception {
+ System.out.println("ARCH: Checking resource name ...");
+ Vector<ArchiResource> n = new Vector<ArchiResource>(arch.getProcessorList());
+ n.addAll(arch.getMemoryList());
+
+ //sort resources in n by name
+ Collections.sort(n,
+ new Comparator<ArchiResource>()
+ {
+ public int compare(ArchiResource resource1, ArchiResource resource2) {
+ return resource1.getName().compareTo(resource2.getName());
+ }
+ } );
+
+ //test adjacent resources in n for equal name
+ for (int k = 0; k < n.size() - 1; k++)
+ {
+ if (((ArchiResource) n.elementAt(k)).getName().equals(
+ ((ArchiResource) n.elementAt(k + 1)).getName())) {
+ throw new Exception("Name conflict: " +
+ ((ArchiResource)n.elementAt(k + 1)).getName() +
+ " appears (at least) twice.");
+ }
+ }
+ }
+
+ /**
+ * every processor of type NETSIM must have a configuration tag with
+ * name "address" and one with name "port". these address-port pairs
+ * have to be unique
+ * @param arch
+ * @throws Exception
+ */
+ private void _checkNETSIM(Architecture arch) throws Exception
+ {
+ System.out.println("ARCH: Checking network simulators ...");
+
+ Vector<Processor> sockets = new Vector<Processor>();
+
+ for (Processor proc : arch.getProcessorList()) {
+ if ( proc.getType().equals("NETSIM") )
+ {
+ if ( proc.getCfg("address") == null
+ || proc.getCfg("port") == null )
+ {
+ throw new Exception("Processor " + proc.getName() +
+ " is of type NETSIM but address or port is missing");
+ }
+ if ( proc.getCfg("address").equals("")
+ || proc.getCfg("port").equals("") )
+ {
+ throw new Exception("Processor " + proc.getName() +
+ " has empty address or port");
+ }
+ sockets.add(proc); // add processor to socket list
+ }
+ }
+
+ /* socket comperator */
+ Comparator<Processor> sockComp = new Comparator<Processor>()
+ {
+ public int compare(Processor proc1, Processor proc2)
+ {
+ String ad1, ad2;
+ ad1 = proc1.getCfg("address").getValue();
+ ad2 = proc2.getCfg("address").getValue();
+
+ int comp = ad1.compareToIgnoreCase(ad2);
+
+ if (comp != 0)
+ {
+ return comp;
+ }
+ else
+ {
+ String p1, p2;
+ p1 = proc1.getCfg("port").getValue();
+ p2 = proc2.getCfg("port").getValue();
+
+ return p1.compareToIgnoreCase(p2);
+ }
+ }
+ };
+
+
+ /* sort sockets */
+ Collections.sort(sockets, sockComp);
+
+ /* check for uniqueness */
+ Processor proc1 = null;
+ Processor proc2 = null;
+ if (!sockets.isEmpty())
+ proc1 = sockets.get(0);
+ for (int i=1; i<sockets.size(); i++)
+ {
+ proc2 = sockets.get(i);
+ if (sockComp.compare(proc1, proc2) == 0)
+ {
+ throw new Exception("multiple processors with hostname \"" +
+ proc1.getCfg("address").getValue() +
+ "\" and port " + proc1.getCfg("port").getValue() +
+ " exist");
+ }
+ proc1 = proc2;
+ }
+ } // _checkNETSIM()
+
+
+ /**
+ * Checks that exactly one master simulator is defined if
+ * processors of type "NETSIM" exist.
+ * @param arch the architecture to check
+ * @throws Exception
+ */
+ private void _checkMaster(Architecture arch) throws Exception
+ {
+ boolean hasMaster = false;
+ boolean hasHosts = false;
+
+ for (Processor p : arch.getProcessorList()) {
+ if (p.getType().equals("NETSIM"))
+ {
+ hasHosts = true;
+ Configuration opt = p.getCfg("master");
+ if (opt != null && opt.getValue().equals("true"))
+ {
+ if (hasMaster)
+ throw new Exception("multiple master simulators"
+ + "defined");
+ else
+ hasMaster = true;
+
+ }
+ }
+ }
+
+ if (hasHosts && !hasMaster)
+ throw new Exception("no master simulator defined");
+
+ } // _checkMaster()
+
+ /**
+ * Check that software resources bind only to one hardware resource.
+ *
+ * @param map mapping to check
+ */
+ private void _checkMultibind(Mapping map) throws Exception {
+ System.out.println("MAP: Checking multiple bindings ...");
+ Vector<Process> processes = map.getProcessList();
+
+ //sort processes in n by name
+ Collections.sort(processes,
+ new Comparator<Process>()
+ {
+ public int compare(Process p1, Process p2) {
+ return p1.getName().compareTo(p2.getName());
+ }
+ } );
+
+ //test adjacent origins for equal name
+ String o1 = null;
+ String o2 = null;
+ if (!processes.isEmpty())
+ o1 = processes.get(0).getName();
+ for (int k = 1; k < processes.size(); k++)
+ {
+ o2 = processes.get(k).getName();
+ if (o1.equals(o2))
+ {
+ throw new Exception("sw resource \"" + o1 +
+ "\" has multiple bindings");
+ }
+ }
+ }
+
+ /**
+ * Checks that every process is bound to a processor.
+ * @param map the map to check
+ * @throws Exception if not all processes are bound to a processor
+ */
+ private void _checkProcessesBound(Mapping map) throws Exception
+ {
+ System.out.println("MAP: Checking that all processes have a binding ...");
+ Vector<Process> boundList = map.getProcessList();
+ Vector<Process> totalList = map.getPN().getProcessList();
+
+ if (boundList.size() != totalList.size())
+ {
+ throw new Exception("some processes are not bound to a processor");
+ }
+ }
+
+ /**
+ * singleton instance
+ */
+ private final static SanityCheck _instance = new SanityCheck();
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Consistency checker for DOL spcific XML files.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: XmlTag.java 203 2010-10-11 08:59:47Z dchokshi $ */
+package dol.datamodel;
+
+
+/**
+ * Class to store XML tag for xml element
+ */
+public class XmlTag {
+
+ /**
+ * Get a single instance of the XmlTag object.
+ */
+ private final static XmlTag _instance = new XmlTag();
+
+ /**
+ * Constructor. Private since only a single version may exist.
+ */
+ private XmlTag() {}
+
+ /**
+ * returns the singleton instance of this class.
+ *
+ * @return The instance value
+ */
+ public final static XmlTag getInstance() { return _instance; }
+
+ // processnetwork XML tag
+ public final String getPNTag() { return "processnetwork";}
+ public final String getVariableTag() { return "variable";}
+ public final String getProcessTag() { return "process";}
+ public final String getSWChannelTag() { return "sw_channel";}
+ public final String getPortTag() { return "port";}
+ public final String getSourceTag() { return "source";}
+ public final String getProfilingTag() { return "profiling";}
+
+ // architecture XML tag
+ public final String getArchiTag() { return "architecture";}
+ public final String getProcessorTag() { return "processor";}
+ public final String getMemoryTag() { return "memory";}
+ public final String getNodeTag() { return "node";}
+ public final String getInPortTag() { return "inputport";}
+ public final String getOutPortTag() { return "outputport";}
+ public final String getDuplexPortTag() { return "duplexport";}
+ public final String getHWChannelTag() { return "hw_channel";}
+ public final String getReadPathTag() { return "readpath";}
+ public final String getWritePathTag() { return "writepath";}
+ public final String getTXBufTag() { return "txbuf";}
+ public final String getRXBufTag() { return "rxbuf";}
+ public final String getCHBufTag() { return "chbuf";}
+
+ // mapping XML tag
+ public final String getMappingTag() { return "mapping";}
+ public final String getBindingTag() { return "binding";}
+ public final String getScheduleTag() { return "schedule";}
+ public final String getResourceTag() { return "resource";}
+
+ // common tag
+ public final String getConfigurationTag() { return "configuration";}
+
+ //iterator related XML tag
+ public final String getIteratorTag() { return "iterator";}
+ public final String getFunctionTag() { return "function";}
+ public final String getAppendTag() { return "append";}
+
+ // connection tag
+ public final String getConnectionTag() { return "connection";}
+ public final String getOriginTag() { return "origin";}
+ public final String getTargetTag() { return "target";}
+
+ // processnetwork profiling value
+ public final String getProfilingTotalReadData() { return "TotalReadData";}
+ public final String getProfilingNumOfReads() { return "NumOfReads";}
+ public final String getProfilingNumOfWrites() { return "NumOfWrites";}
+ public final String getProfilingNumOfFires() { return "NumOfFires";}
+}
+
--- /dev/null
+/* $Id: ArchiConnection.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class defines an architecture connection. Used in the simplified
+ * architecture specification. An architecture connection contains one
+ * origin and one target resource.
+ */
+public class ArchiConnection extends ArchiResource {
+ /**
+ * Constructor to create an architecture connection with a name.
+ *
+ */
+ public ArchiConnection(String name) {
+ super(name);
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this architectural connection.
+ *
+ * @return a new instance of the architectural connection.
+ */
+ public Object clone() {
+ ArchiConnection newObj = (ArchiConnection) super.clone();
+ newObj.setOrigin(_origin);
+ newObj.setTarget(_target);
+ return (newObj);
+ }
+
+ /**
+ * Return a string representation of the architectural connection.
+ *
+ * @return string representation of the architectural connection
+ */
+ public String toString() {
+ return "ArchiConnection: " + getName();
+ }
+
+ /**
+ * Return the origin of the architectural connection.
+ *
+ * @return origin architectural resource of the architectural connection
+ */
+ public ArchiResource getOrigin() { return _origin; }
+
+ /**
+ * Set the origin of the architectural connection.
+ *
+ * @param origin architectural resource.
+ */
+ public void setOrigin(ArchiResource origin) { _origin = origin; }
+
+ /**
+ * Return the target of the architectural connection.
+ *
+ * @return target architectural resource of the architectural connection
+ */
+ public ArchiResource getTarget() { return _target; }
+
+ /**
+ * Set the target of the architectural connection.
+ *
+ * @param target architectural resource.
+ */
+ public void setTarget(ArchiResource target) { _target = target; }
+
+ protected ArchiResource _origin;
+ protected ArchiResource _target;
+}
--- /dev/null
+/* $Id: ArchiResource.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class is the basic class which abstracts an architectural resource
+ * of a generic architecture. The architectural resource has a name and a
+ * list of included nodes.
+ */
+public class ArchiResource implements Cloneable {
+ /**
+ * Constructor to create an architectural resource with a name and
+ * an empty node list.
+ */
+ public ArchiResource(String name) {
+ _name = name;
+ _basename = name;
+ _nodeList = new Vector<Node>();
+ _cfgList = new Vector<Configuration>();
+ }
+
+ /**
+ * Accept a Visitor
+ *
+ * @param x visitor object
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this architectural resource.
+ *
+ * @return new instance of the architectural resource.
+ */
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ try {
+ ArchiResource newObj = (ArchiResource) super.clone();
+ newObj.setName(_name);
+ newObj.setBasename(_basename);
+ newObj.setNodeList((Vector)_nodeList.clone() );
+ newObj.setCfgList((Vector)_cfgList.clone() );
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the name of this architectural resource.
+ *
+ * @return name of the architectural resource
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this architectural resource.
+ *
+ * @param name name of the architectural resource
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the basename of this architectural resource.
+ *
+ * @return basename of the architectural resource
+ */
+ public String getBasename() {
+ return _basename;
+ }
+
+ /**
+ * Set the basename of this architectural resource.
+ *
+ * @param basename name of the architectural resource
+ */
+ public void setBasename(String basename) {
+ _basename = basename;
+ }
+
+ /**
+ * Get the iterator indices of this process.
+ *
+ * @return range
+ */
+ public Vector<Integer> getIteratorIndices() {
+ Vector<Integer> indices = new Vector<Integer>();
+ StringTokenizer tokenizer =
+ new StringTokenizer(_name.replaceAll(_basename, ""), "_");
+ while (tokenizer.hasMoreTokens()) {
+ indices.add(Integer.valueOf(tokenizer.nextToken()));
+ }
+ return indices;
+ }
+
+ /**
+ * Get the list of nodes of this architectural resource.
+ *
+ * @return list of nodes
+ */
+ public Vector<Node> getNodeList() {
+ return _nodeList;
+ }
+
+ /**
+ * Set the list of nodes of this architectural resource.
+ *
+ * @param nodeList nodes list
+ */
+ public void setNodeList(Vector<Node> nodeList) {
+ _nodeList = nodeList;
+ }
+
+ /**
+ * Get the hierarchical parent of this architectural resource.
+ *
+ * @return parent of this architectural resource
+ */
+ public ArchiResource getParentResource() {
+ return _parentResource;
+ }
+
+ /**
+ * Set the hierarchical parent of this architectural resource.
+ *
+ * @param parentResource new parent
+ */
+ public void setParentResource(ArchiResource parentResource) {
+ _parentResource = parentResource;
+ }
+
+ /**
+ * Return a string representation of the architectural resource.
+ *
+ * @return string representation of the architectural resource
+ */
+ public String toString() {
+ return "ArchiResource: " + _name;
+ }
+
+ /**
+ * Return a node (which has a specific name). Return null when node
+ * cannot be found.
+ *
+ * @param name of the node to search for
+ * @return node with the specified name
+ */
+ public Node getNode(String name) {
+ Iterator<Node> i;
+ i = _nodeList.iterator();
+ while (i.hasNext()) {
+ Node node = i.next();
+ if (node.getName().equals(name)) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return a node. Return null when node cannot be found.
+ *
+ * @return node
+ */
+ public Node getNode() {
+ Iterator<Node> i;
+ i = _nodeList.iterator();
+ while (i.hasNext()) {
+ Node node = i.next();
+ return node;
+ }
+ return null;
+ }
+
+ /**
+ * Has this resource nodes?
+ *
+ * @return boolean value
+ */
+ public boolean hasNodes() {
+ return !_nodeList.isEmpty();
+ }
+
+
+ /**
+ * Return the first node of the nodelist.
+ *
+ * @return the first node of the nodelist.
+ */
+ public Node getFirstNode() {
+ return (Node) _nodeList.firstElement();
+ }
+
+ /**
+ * Get the list of configurations of this resource.
+ *
+ * @return list of configurations
+ */
+ public Vector<Configuration> getCfgList() {
+ return _cfgList;
+ }
+
+ /**
+ * Set the list of configurations of this resource.
+ *
+ * @param cfgList configuration list
+ */
+ public void setCfgList(Vector<Configuration> cfgList) {
+ _cfgList = cfgList;
+ }
+
+ /**
+ * Return a configuration which has a specific name. Return
+ * null when configuration cannot be found.
+ *
+ * @param name name of the configuration to search for
+ * @return configuration with the specified name
+ */
+ public Configuration getCfg(String name) {
+ for (Configuration config : _cfgList) {
+ if (config.getName().equals(name)) {
+ return config;
+ }
+ }
+ return null;
+ }
+
+
+ /** list of the configurations of the ArchiResource */
+ protected Vector<Configuration> _cfgList = null;
+
+ /** name of the architectural resource */
+ protected String _name = null;
+
+ /** basename of the architectural resource, if no basename, store the name */
+ protected String _basename = null;
+
+ /** list of the nodes, paths of the architectural resource */
+ protected Vector<Node> _nodeList = null;
+
+ /** parent resource of this architectural resource */
+ protected ArchiResource _parentResource = null;
+}
--- /dev/null
+/* $Id: Architecture.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+import dol.visitor.ArchiVisitor;
+
+
+/**
+ * This class defines an architecture.
+ */
+public class Architecture extends ArchiResource {
+ /**
+ * Constructor to create an architecture with a name,
+ * empty processor list, empty memory list, empty hwChannel list and empty connection list.
+ */
+ public Architecture(String name) {
+ super(name);
+ _processorList = new Vector<Processor>();
+ _memoryList = new Vector<Memory>();
+ _hwChannelList = new Vector<HWChannel>();
+ _varList = new Vector<Variable>();
+ _connectionList = new Vector<ArchiConnection>();
+ _readPathList = new Vector<ReadPath>();
+ _writePathList = new Vector<WritePath>();
+ _pathList = new Vector<Path>();
+ _processorPathList = new Hashtable<Processor,
+ Hashtable<Processor, Vector<Path>>>();
+
+ }
+
+ /**
+ * Accept a visitor
+ *
+ * @param x visitor object
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Architecture.
+ *
+ * @return new instance of the Architecure
+ */
+ /*
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ Architecture newObj = (Architecture) super.clone();
+ newObj.setProcessorList((Vector<Processor>)_processorList.clone());
+ newObj.setMemoryList((Vector<Memory>)_memoryList.clone());
+ newObj.setHWChannelList((Vector<HWChannel>)_hwChannelList.clone());
+ newObj.setVarList((Vector<Variable>)_varList.clone());
+ newObj.setConnectionList((Vector<ArchiConnection>)_connectionList.clone());
+ newObj.setReadPathList((Vector<ReadPath>)_readPathList.clone());
+ newObj.setWritePathList((Vector<WritePath>)_writePathList.clone());
+ newObj.setPathList((Vector<Vector<Node>>)_pathList.clone());
+ return newObj;
+ }
+ */
+
+
+ /**
+ * Get the processor list of a Architecture.
+ *
+ * @return the processor list
+ */
+ public Vector<Processor> getProcessorList() {
+ return _processorList;
+ }
+
+ /**
+ * Get the memory list of a Architecture.
+ *
+ * @return the memory list
+ */
+ public Vector<Memory> getMemoryList() {
+ return _memoryList;
+ }
+
+ /**
+ * Get the hwChannel list of a Architecture.
+ *
+ * @return the hwChannel list
+ */
+ public Vector<HWChannel> getHWChannelList() {
+ return _hwChannelList;
+ }
+
+ /**
+ * Get the paths list of a Architecture.
+ *
+ * @return the paths list
+ */
+ public Vector<ReadPath> getReadPathList() {
+ return _readPathList;
+ }
+
+ /**
+ * Get the write paths list of a Architecture.
+ *
+ * @return the paths list
+ */
+ public Vector<WritePath> getWritePathList( ) {
+ return _writePathList;
+ }
+
+ /**
+ * Set the processor paths list of a Architecture.
+ *
+ * @param pathList The new list
+ */
+ public void setPathList(Vector<Path> pathList) {
+ _pathList = pathList;
+ }
+
+ /**
+ * Get the processor paths list of a Architecture.
+ *
+ * @return the processor paths list
+ */
+ public Vector<Path> getPathList() {
+ return _pathList;
+ }
+
+ /**
+ * Return a processor/memory/hwChannel which has a specific name. Return null if
+ * processor cannot be found.
+ *
+ * @param name the name of the processor/memory/hwChannel to search for.
+ * @return the processor/memory/hwChannel with the specific name.
+ */
+ public Processor getProcessor(String name) {
+ for (Processor processor : _processorList) {
+ if (processor.getName().equals(name)) {
+ return processor;
+ }
+ }
+ return null;
+ }
+
+ /**
+ *
+ */
+ public Memory getMemory(String name) {
+ for (Memory memory : _memoryList) {
+ if (memory.getName().equals(name)) {
+ return memory;
+ }
+ }
+ return null;
+ }
+
+ /**
+ *
+ */
+ public HWChannel getHWChannel(String name) {
+ for (HWChannel hwChannel : _hwChannelList) {
+ if (hwChannel.getName().equals(name)) {
+ return hwChannel;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Return a read path which has a specific name. Return null if
+ * not found.
+ *
+ * @param name the name of the read path to search for.
+ * @return the read path with the specific name.
+ */
+ public ReadPath getReadPath(String name) {
+ for (ReadPath p : _readPathList) {
+ if (p.getName().equals(name)) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return a write path which has a specific name. Return null if
+ * not found.
+ *
+ * @param name the name of the write path to search for.
+ * @return the write path with the specific name.
+ */
+ public WritePath getWritePath(String name) {
+ for (WritePath p : _writePathList) {
+ if (p.getName().equals(name)) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ public Vector<Variable> getVarList() { return _varList; }
+
+ public Vector<ArchiConnection> getConnectionList() {
+ return _connectionList;
+ }
+
+ /**
+ * Compute all paths between processors.
+ */
+ public void computePaths() {
+ for (WritePath w : _writePathList) {
+ String channelBuffer = w.getCHBuf().getName();
+ for (ReadPath r : _readPathList) {
+ if (r.getCHBuf().getName().equals(channelBuffer)) {
+ Path path = new Path();
+ path.setWritePath(w);
+ path.setReadPath(r);
+ _pathList.add(path);
+ }
+ }
+ }
+
+ /*
+ //print all paths in this architecture
+ for (int j = 0; j < _pathList.size(); j++) {
+ Vector<ArchiResource> path = _pathList.elementAt(j).getPath();
+ for (int k = 0; k < path.size(); k++) {
+ System.out.print(path.elementAt(k).
+ getName() + (k < path.size() - 1 ? " -> " : ""));
+ }
+ System.out.println();
+ }
+ System.out.println("Found " + _pathList.size() + " paths.");
+ */
+
+ computeProcessorPath();
+ }
+
+ /**
+ * Compute all write path from one processor to another processor
+ * in this architecture.
+ */
+ protected void computeProcessorPath() {
+ //iterate over all path in this architecture
+ for (int j = 0; j < _pathList.size(); j++) {
+ Processor startProcessor = _pathList.elementAt(j).getStartProcessor();
+ Processor targetProcessor = _pathList.elementAt(j).getTargetProcessor();
+
+ //create new hashtable entry for this start processor
+ if (!_processorPathList.containsKey(startProcessor)) {
+ Hashtable<Processor, Vector<Path>>
+ processorPathList = new Hashtable<Processor,
+ Vector<Path>>();
+ _processorPathList.put(startProcessor, processorPathList);
+ }
+
+ Hashtable<Processor, Vector<Path>>
+ processorPathList = _processorPathList.
+ get(startProcessor);
+
+ //create new path list for this target processor
+ if(!processorPathList.containsKey(targetProcessor)) {
+ Vector<Path> processorPath = new Vector<Path>();
+ processorPathList.put(targetProcessor, processorPath);
+ }
+
+ Vector<Path> processorPath =
+ processorPathList.get(targetProcessor);
+
+ //add this path to the list of paths
+ processorPath.add(_pathList.elementAt(j));
+ }
+
+ /*
+ //print all processor to processor path
+ int pathCounter = 0;
+ for (int j = 0; j < _processorList.size(); j++) {
+ for (int k = 0; k < _processorList.size(); k++) {
+ Vector<Path> processorPathList =
+ getPaths(_processorList.elementAt(j),
+ _processorList.elementAt(k));
+ for (int l = 0; l < processorPathList.size(); l++) {
+ pathCounter++;
+ Vector<ArchiResource> path = processorPathList.
+ elementAt(l).getPath();
+ for (int m = 0; m < path.size(); m++) {
+ System.out.print(path.elementAt(m).getName()
+ + (m < path.size() - 1 ? " -> " : ""));
+ }
+ System.out.println();
+ }
+ }
+ }
+ System.out.println("Found " + pathCounter + " paths.");
+ */
+ }
+
+ /**
+ * Get all write paths from the given start processor to the given
+ * target processor.
+ *
+ * @param startProcessor processor where write path begins
+ * @param targetProcessor processor where write path ends
+ * @return vector of all write paths between startProcessor and
+ * targetProcessor
+ */
+ public Vector<Path> getPaths(
+ Processor startProcessor, Processor targetProcessor) {
+ if (_processorPathList.get(startProcessor) == null) {
+ return null;
+ }
+ return _processorPathList.get(startProcessor).get(targetProcessor);
+ }
+
+ /**
+ * Register the RX/TX/CH buffer to each resource.
+ * Can be used for dotty generation.
+ */
+ public void registerRWPath2Resource()
+ {
+ for (ReadPath r : _readPathList) {
+ // register rxbuf
+ String memName = r.getRXBuf().getName();
+ for (Memory m : _memoryList) {
+ if (m.getName().equals(memName)) {
+ m.getRXBufList().add(r.getName());
+ }
+ }
+
+ // register chbuf
+ memName = r.getCHBuf().getName();
+ for (Memory m : _memoryList) {
+ if (m.getName().equals(memName)) {
+ m.getCHBufList().add(r.getName() + "_RPath");
+ }
+ }
+
+ // register pathes via a communication resource
+ for (HWChannel c : r.getHWChannelList()) {
+ if (c.getName().equals(r.getName())) {
+ // premise: a path cannot go via a bus twice.
+ c.getPathList().add(r.getName() + "_RPath");
+ }
+ }
+ }
+
+ for (WritePath w : _writePathList) {
+ // register txbuf
+ String memName = w.getTXBuf().getName();
+ for (Memory m : _memoryList) {
+ if (m.getName().equals(memName)) {
+ m.getTXBufList().add(w.getName());
+ }
+ }
+
+ // register chbuf
+ memName = w.getCHBuf().getName();
+ for (Memory m : _memoryList) {
+ if (m.getName().equals(memName)) {
+ m.getCHBufList().add(w.getName() + "_WPath");
+ }
+ }
+
+ // register pathes via a communication resource
+ for (HWChannel c : w.getHWChannelList()) {
+ if (c.getName().equals(w.getName())) {
+ // premise: a path cannot go via a bus twice.
+ c.getPathList().add(w.getName() + "_WPath");
+ }
+ }
+ }
+ }
+
+ /** List of the processors in the Architecture */
+ protected Vector<Processor> _processorList = null;
+
+ /** List of the memories in the Architecture */
+ protected Vector<Memory> _memoryList = null;
+
+ /** List of hwChannels in the Architecture */
+ protected Vector<HWChannel> _hwChannelList = null;
+
+ /** List of variables in the Architecture */
+ protected Vector<Variable> _varList = null;
+
+ /** List of connections in the Architecture: for simplified arch*/
+ protected Vector<ArchiConnection> _connectionList = null;
+
+ /** List of read paths in the Architecture: for detail arch */
+ protected Vector<ReadPath> _readPathList = null;
+
+ /** List of write paths in the Architecture: for detail arch */
+ protected Vector<WritePath> _writePathList = null;
+
+ /** List of paths in the Architecture */
+ protected Vector<Path> _pathList = null;
+
+ /** hashtable to access all processor to processor path */
+ protected Hashtable<Processor, Hashtable<Processor,
+ Vector<Path>>> _processorPathList = null;
+}
--- /dev/null
+/* $Id: Configuration.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+
+/**
+ * This class represents a name-value pair of a configuration tag in XML.
+ */
+public class Configuration {
+
+ /**
+ * Constructor to create a Configuration.
+ */
+ public Configuration(String name) {
+ _name = name;
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+ */
+
+
+ /**
+ * Clone this Configuration.
+ *
+ * @return new instance of the Configuration.
+ */
+ public Object clone() {
+ try {
+ Configuration newObj = (Configuration) super.clone();
+ newObj.setName(_name);
+ newObj.setValue(_value);
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the value of the Configuration.
+ *
+ * @return the value of the configuration.
+ */
+ public String getValue() {
+ return _value;
+ }
+
+ /**
+ * Set the value of the Configuration.
+ *
+ * @param value the value of the configuration.
+ */
+ public void setValue(String value) {
+ _value = value;
+ }
+
+ /**
+ * Get the name of this configuration.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this configuration.
+ *
+ * @param name name of the configuration
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the hierarchical parent of this resource.
+ *
+ * @return parent of this resource
+
+ public Resource getParentResource() {
+ return _parentResource;
+ }
+ */
+
+ /**
+ * Set the hierarchical parent of this resource.
+ *
+ * @param parentResource new parent
+
+ public void setParentResource(Resource parentResource) {
+ _parentResource = parentResource;
+ }
+ */
+
+ /**
+ * Return a string representation of the Configuration.
+ *
+ * @return string representation of the Configuration
+ */
+ public String toString() {
+ return "Configuration: " + getName();
+ }
+
+ protected String _value = null;
+ protected String _name = null;
+ protected ArchiResource _parentResource = null;
+}
--- /dev/null
+/* $Id: HWChannel.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class represents an interconnect element in the architecture.
+ */
+public class HWChannel extends ArchiResource {
+ /**
+ * Constructor to create a HWChannel with a name and an empty
+ * nodeList.
+ */
+ public HWChannel(String name) {
+ super(name);
+ _pathList = new Vector<String>();
+ }
+
+ /**
+ * Accept a Visitor
+ * @param x A Visitor Object.
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this HWChannel
+ *
+ * @return a new instance of the HWChannel.
+ */
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ HWChannel newObj = (HWChannel) super.clone();
+ newObj.setPathList((Vector<String>)_pathList.clone());
+ return (newObj);
+ }
+
+ /**
+ * Get the range of this processor.
+ *
+ * @return range
+ */
+ public String getRange() {
+ return _range;
+ }
+
+ /**
+ * Set the range of this process.
+ *
+ * @param range new range value
+ */
+ public void setRange(String range) {
+ _range= range;
+ }
+
+ /**
+ * Get the type of this hw_channel.
+ *
+ * @return type
+ */
+ public String getType() {
+ return _type;
+ }
+
+ /**
+ * Set the type of this hw_channel.
+ *
+ * @param type new range value
+ */
+ public void setType(String type) {
+ _type= type;
+ }
+
+ /**
+ * Has this processor nodes?
+ *
+ * @return boolean value
+ */
+ public boolean hasNodes() {
+ Iterator<Node> i = getNodeList().iterator();
+ while (i.hasNext()) {
+ i.next();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the list of pathes via this resource.
+ *
+ * @return list of path.
+ */
+ public Vector<String> getPathList() {
+ return _pathList;
+ }
+
+ /**
+ * Set the list of pathes via this resource.
+ *
+ * @param list path list
+ */
+ public void setPathList(Vector<String> list) {
+ _pathList = list;
+ }
+
+ /**
+ * Return a description of the processor.
+ *
+ * @return a description of the processor.
+ */
+ public String toString() {
+ return "HWChannel: " + getName() ;
+ }
+
+ /**
+ * Range of the iterator when the instance belongs to an iterated
+ * series of processors.
+ */
+ protected String _range;
+ protected String _type;
+
+ // Store the name of pathes which go via this communication resource.
+ protected Vector<String> _pathList;
+}
--- /dev/null
+/* $Id: Memory.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class represents a memory element in the archietcture.
+ */
+public class Memory extends ArchiResource {
+ /**
+ * Constructor to create a Memory with a name and an empty
+ * nodeList.
+ */
+ public Memory(String name) {
+ super(name);
+ _rxBufList = new Vector<String>();
+ _txBufList = new Vector<String>();
+ _chBufList = new Vector<String>();
+ }
+
+ /**
+ * Accept a Visitor
+ * @param x A Visitor Object.
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Memory
+ *
+ * @return a new instance of the Memory.
+ */
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ Memory newObj = (Memory) super.clone();
+ newObj.setRXBufList((Vector<String>)_rxBufList.clone());
+ newObj.setTXBufList((Vector<String>)_txBufList.clone());
+ newObj.setCHBufList((Vector<String>)_chBufList.clone());
+ return (newObj);
+ }
+
+ /**
+ * Get the range of this Memory.
+ *
+ * @return range
+ */
+ public String getRange() {
+ return _range;
+ }
+
+ /**
+ * Set the range of this Memory.
+ *
+ * @param range new range value
+ */
+ public void setRange(String range) {
+ _range= range;
+ }
+
+ /**
+ * Get the type of this Memory.
+ *
+ * @return type
+ */
+ public String getType() {
+ return _type;
+ }
+
+ /**
+ * Set the type of this Memory.
+ *
+ * @param type new range value
+ */
+ public void setType(String type) {
+ _type= type;
+ }
+
+ /**
+ * Get the list of RXBuf of this memory
+ *
+ * @return list of RX buffer.
+ */
+ public Vector<String> getRXBufList() {
+ return _rxBufList;
+ }
+
+ /**
+ * Set the list of RXBuf of this memory.
+ *
+ * @param list RX buffer list
+ */
+ public void setRXBufList(Vector<String> list) {
+ _rxBufList = list;
+ }
+
+ /**
+ * Get the list of TXBuf of this memory.
+ *
+ * @return list of TX buffers.
+ */
+ public Vector<String> getTXBufList() {
+ return _txBufList;
+ }
+
+ /**
+ * Set the list of TXBuf of this memory.
+ *
+ * @param list TX buffer list
+ */
+ public void setTXBufList(Vector<String> list) {
+ _txBufList = list;
+ }
+
+ /**
+ * Get the list of channel buffers of this memory.
+ *
+ * @return list of channel buffers.
+ */
+ public Vector<String> getCHBufList() {
+ return _chBufList;
+ }
+
+ /**
+ * Set the list of channel Buf of this memory.
+ *
+ * @param list channel buffer list
+ */
+ public void setCHBufList(Vector<String> list) {
+ _chBufList = list;
+ }
+
+ /**
+ * Has this memory nodes?
+ *
+ * @return boolean value
+ */
+ public boolean hasNodes() {
+ Iterator<Node> i = getNodeList().iterator();
+ while (i.hasNext()) {
+ i.next();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return a description of the Memory.
+ *
+ * @return a description of the Memory.
+ */
+ public String toString() {
+ return "Memory: " + getName() ;
+ }
+
+ /**
+ * Range of the iterator when the instance belongs to an iterated
+ * series of Memories.
+ */
+ protected String _range;
+ protected String _type;
+
+ // store the name of rx, tx channel buffer, can be used for dotty gen.
+ protected Vector<String> _rxBufList;
+ protected Vector<String> _txBufList;
+ protected Vector<String> _chBufList;
+}
--- /dev/null
+/* $Id: Node.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Vector;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class represents a node in the archietcture.
+ */
+public class Node implements Cloneable {
+
+ /**
+ * Constructor to create a Node with a name and an empty
+ * portList.
+ */
+ public Node(String name) {
+ _name = name;
+ _basename = name;
+ _portList = new Vector<PortNode>();
+ }
+
+ /**
+ * Accept a Visitor
+ * @param x A Visitor Object.
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Node
+ *
+ * @return a new instance of the Node.
+ */
+ public Object clone() {
+ try {
+ Node newObj = (Node) super.clone();
+ newObj.setName(_name);
+ newObj.setBasename(_basename);
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the range of this node.
+ *
+ * @return range
+ */
+ public String getRange() {
+ return _range;
+ }
+
+ /**
+ * Set the range of this node.
+ *
+ * @param range new range value
+ */
+ public void setRange(String range) {
+ _range= range;
+ }
+
+
+ /**
+ * Get the name of this node.
+ *
+ * @return name of the node
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this node.
+ *
+ * @param name name of the node
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the basename of this node.
+ *
+ * @return basename of the node
+ */
+ public String getBasename() {
+ return _basename;
+ }
+
+ /**
+ * Set the basename of this node.
+ *
+ * @param basename name of the node
+ */
+ public void setBasename(String basename) {
+ _basename = basename;
+ }
+
+ /**
+ * Has this node IN/OUT/INOUT ports?
+ *
+ * @return boolean value
+ */
+ public boolean hasInPorts() {
+ for (PortNode port : getPortList()) {
+ if (port.isInPort())
+ return true;
+ }
+ return false;
+ }
+
+ public boolean hasOutPorts() {
+ for (PortNode port : getPortList()) {
+ if (port.isOutPort())
+ return true;
+ }
+ return false;
+ }
+
+ public boolean hasInOutPorts() {
+ for (PortNode port : getPortList()) {
+ if (port.isInOutPort())
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return a port which has a specific name. Return null when port
+ * cannot be found.
+ *
+ * @param name name of the port to search for
+ * @return port with the specified name
+ */
+ public PortNode getPort(String name) {
+ for (PortNode port : getPortList()) {
+ if (port.getName().equals(name)) {
+ return port;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the first port on the List.
+ *
+ * @return first port element
+ */
+ public PortNode getFirstPort() {
+ return (PortNode) _portList.firstElement();
+ }
+
+ /**
+ * Get the corresponding ArchiResource.
+ *
+ * @return the corresponding ArchiResource
+ */
+ public ArchiResource getCorrespResource() {
+ return _correspResource;
+ }
+
+ /**
+ * Set the corresponding ArchiResource.
+ *
+ * @param correspResource new ArchiResource
+ */
+ public void setCorrespResource(ArchiResource correspResource) {
+ _correspResource = correspResource;
+ }
+
+ /**
+ * Get the port list of a Node.
+ *
+ * @return the port list
+ */
+ public Vector<PortNode> getPortList() {
+ return _portList;
+ }
+
+ /**
+ * Set the port list of a Node.
+ *
+ * @param portList The new list
+ */
+ public void setPortList( Vector<PortNode> portList ) {
+ _portList = portList;
+ }
+
+ /**
+ * Return a description of the node.
+ *
+ * @return a description of the node.
+ */
+ public String toString() {
+ return "Node: " + getName();
+ }
+
+ /**
+ * Range of the iterator when the instance belongs to an iterated
+ * series of nodes.
+ */
+ protected String _range;
+ protected String _name = null;
+ protected String _basename = null;
+ protected ArchiResource _correspResource = null;
+ protected Vector<PortNode> _portList = null;
+}
--- /dev/null
+/* $Id: Path.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+/**
+ * Path consisting of write path and read path.
+ */
+public class Path {
+ /**
+ * Default constructor.
+ */
+ public Path() {
+ _path = new Vector<ArchiResource>();
+ }
+
+ /**
+ * Set the read path of this path.
+ */
+ public void setReadPath(ReadPath readPath) {
+ _readPath = readPath;
+ computeArchitectureResources();
+ }
+
+ /**
+ * Return the read path of this path.
+ *
+ * @return read path
+ */
+ public ReadPath getReadPath() {
+ return _readPath;
+ }
+
+ /**
+ * Set the write path of this path.
+ */
+ public void setWritePath(WritePath writePath) {
+ _writePath = writePath;
+ computeArchitectureResources();
+ }
+
+ /**
+ * Return the write path of this path.
+ *
+ * @return write path
+ */
+ public WritePath getWritePath() {
+ return _writePath;
+ }
+
+ /**
+ * Return all resources contained in this path.
+ *
+ * @return all resources contained in this path
+ */
+ public Vector<ArchiResource> getPath() {
+ return _path;
+ }
+
+ /**
+ * Return the processor where this path starts.
+ *
+ * @return processor where this path starts
+ */
+ public Processor getStartProcessor() {
+ if (_path.size() == 0)
+ return null;
+
+ return (Processor)_path.elementAt(0);
+ }
+
+ /**
+ * Return the processor where this path ends.
+ *
+ * @return processor where this path ends
+ */
+ public Processor getTargetProcessor() {
+ if (_path.size() == 0)
+ return null;
+
+ return (Processor)_path.elementAt(_path.size() - 1);
+ }
+
+ /**
+ * Compute the vector of all resources contained in this path.
+ */
+ protected void computeArchitectureResources() {
+ _path.clear();
+
+ if (_readPath == null || _writePath == null)
+ return;
+
+ _path.add(_writePath.getProcessor());
+ _path.add(_writePath.getTXBuf());
+ Iterator<HWChannel> channelIterator =
+ _writePath.getHWChannelList().iterator();
+ while (channelIterator.hasNext()) {
+ _path.add(channelIterator.next());
+ }
+ _path.add(_readPath.getCHBuf());
+ channelIterator = _readPath.getHWChannelList().iterator();
+ while (channelIterator.hasNext()) {
+ _path.add(channelIterator.next());
+ }
+ _path.add(_readPath.getRXBuf());
+ _path.add(_readPath.getProcessor());
+ }
+
+ /** read path of this path*/
+ protected ReadPath _readPath = null;
+
+ /** write path of this path */
+ protected WritePath _writePath = null;
+
+ /** resources contained in this path */
+ Vector<ArchiResource> _path;
+}
--- /dev/null
+/* $Id: PortNode.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class represents a port of an architectural node.
+ */
+public class PortNode implements Cloneable {
+ /**
+ * Constructor to create a PortNode with a name.
+ */
+ public PortNode(String name) {
+ _name = name;
+ _isInPort = false;
+ _isOutPort = false;
+ _isInOutPort = false;
+ }
+
+ /**
+ * Constructor to create a PortNode with a name and a type.
+ */
+ public PortNode(String name, boolean type) {
+ _name = name;
+ _isInPort = (type == INPORT);
+ _isOutPort = (type == OUTPORT);
+ _isInOutPort = (type == INOUTPORT);
+ }
+
+ /**
+ * Accept a visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this PortNode
+ *
+ * @return new instance of the PortNode
+ */
+ public Object clone() {
+ try {
+ PortNode newObj = (PortNode) super.clone();
+ newObj.setName(_name);
+ newObj.setBasename(_basename);
+ newObj.setPeerPort(_peerPort);
+ newObj.setPeerResource(_peerResource);
+ newObj.setPeerNode(_peerNode);
+ newObj.setResource(_resource );
+ newObj.setNode(_node);
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Check whether this port is an inport.
+ *
+ * @return true if this port is an inport, otherwise false
+ */
+ public boolean isInPort() {
+ return _isInPort;
+ }
+
+ /**
+ * Check whether this port is an outport.
+ *
+ * @return true if this port is an outport, otherwise false
+ */
+ public boolean isOutPort() {
+ return _isOutPort;
+ }
+
+ /**
+ * Check whether this port is an inoutport.
+ *
+ * @return true if this port is an inoutport, otherwise false
+ */
+ public boolean isInOutPort() {
+ return _isInOutPort;
+ }
+
+ /**
+ * Get the name of this port.
+ *
+ * @return name of the port
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this port.
+ *
+ * @param name name of the port
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ public void setBasename(String basename) { _basename = basename; }
+ public String getBasename() { return _basename; }
+
+ /**
+ * Get the range of this port.
+ *
+ * @return range of the port
+ */
+ public String getRange() {
+ return _range;
+ }
+
+ /**
+ * Set the range of this port.
+ *
+ * @param range range of the port
+ */
+ public void setRange(String range) {
+ _range= range;
+ }
+
+ /**
+ * Get the resource/node of this port.
+ *
+ * @return the resource/node
+ */
+ public ArchiResource getResource() {
+ return _resource;
+ }
+ public Node getNode() {
+ return _node;
+ }
+
+ /**
+ * Set the resource/node of this port.
+ *
+ * @param resource
+ */
+ public void setResource(ArchiResource resource) {
+ _resource = resource;
+ }
+ public void setNode(Node node) {
+ _node = node;
+ }
+
+ /**
+ * Set the peer resource/node/port of this port.
+ *
+ * @param peer The new node
+ */
+ public void setPeerPort(PortNode peer) { _peerPort = peer; }
+
+ /**
+ *
+ */
+ public void setPeerResource(ArchiResource n) { _peerResource = n; }
+
+ /**
+ *
+ */
+ public void setPeerNode(Node n) { _peerNode = n; }
+
+ /**
+ * Get the peer resource/node/port of this port.
+ *
+ * @return the peer resource/node/port
+ */
+ public PortNode getPeerPort(){ return _peerPort; }
+
+ /**
+ *
+ */
+ public ArchiResource getPeerResource() { return _peerResource; }
+
+ /**
+ *
+ */
+ public Node getPeerNode() { return _peerNode; }
+
+ /**
+ * Get the type of this port.
+ *
+ * @return type of this port
+ */
+ public String getType() {
+ if (_isInPort) return "input";
+ if (_isOutPort) return "output";
+ if (_isInOutPort) return "duplex";
+ return "type not set.";
+ }
+
+ /**
+ * Return a string representation of the port.
+ *
+ * @return string representation of the port
+ */
+ public String toString() {
+ return "PortNode: " + _name;
+ }
+
+ /** constant for inport for usage in the constructor **/
+ public static final boolean INPORT = true;
+
+ /** constant for outport for usage in the constructor **/
+ public static final boolean OUTPORT = false;
+
+ /** constant for inoutport for usage in the constructor **/
+ public static final boolean INOUTPORT = false;
+
+ /** defines whether this port is an inport **/
+ protected boolean _isInPort = false;
+
+ /** defines whether this port is an outport **/
+ protected boolean _isOutPort = false;
+
+ /** defines whether this port is an inout **/
+ protected boolean _isInOutPort = false;
+
+ /** name of the port */
+ protected String _name = null;
+
+ /** basename of the resource, if no basename, store the name */
+ protected String _basename = null;
+
+ /** resource (process or channel) this port belongs to */
+ protected ArchiResource _resource = null;
+
+ /** node this port belongs to */
+ protected Node _node = null;
+
+ /** resource which peerPort belongs to */
+ protected ArchiResource _peerResource = null;
+
+ /** node which peerPort belongs to */
+ protected Node _peerNode = null;
+
+ /** connected peer port name */
+ protected PortNode _peerPort = null;
+
+ /** peer channel name */
+ protected String _channelName = null;
+
+ /**
+ * Range of the iterator when the instance belongs to an iterated
+ * series of ports.
+ */
+ protected String _range = null;
+}
--- /dev/null
+/* $Id: Processor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Vector;
+
+import dol.datamodel.pn.Process;
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class represents a processor element in the architecture.
+ */
+public class Processor extends ArchiResource {
+
+ /**
+ * Constructor to create a Processor with a name and an empty
+ * nodeList.
+ */
+ public Processor(String name) {
+ super(name);
+ _processList = new Vector<Process>();
+ }
+
+ /**
+ * Accept a Visitor
+ * @param x A Visitor Object.
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Processor
+ *
+ * @return a new instance of the Processor.
+ */
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ Processor newObj = (Processor) super.clone();
+ newObj.setProcessList((Vector<Process>)_processList.clone());
+ return (newObj);
+ }
+
+ /**
+ * Get the range of this processor.
+ *
+ * @return range
+ */
+ public String getRange() {
+ return _range;
+ }
+
+ /**
+ * Set the range of this process.
+ *
+ * @param range new range value
+ */
+ public void setRange(String range) {
+ _range= range;
+ }
+
+ /**
+ * Get the type of this processor.
+ *
+ * @return type
+ */
+ public String getType() {
+ return _type;
+ }
+
+ /**
+ * Set the type of this processor.
+ *
+ * @param type new range value
+ */
+ public void setType(String type) {
+ _type= type;
+ }
+
+
+
+ /**
+ * Set the list of processes bound to this processor.
+ * @param processList the new process list
+ */
+ public void setProcessList(Vector<Process> processList)
+ {
+ _processList = processList;
+ }
+
+ /**
+ * Get the list of processes bound to this processor.
+ */
+ public Vector<Process> getProcessList()
+ {
+ return _processList;
+ }
+
+ /**
+ * Indicates if a process with a specific name is bound
+ * to this processor.
+ * @param name the name of the process to search for
+ * @return true if a process with the specifed name is bound to this
+ * processor
+ */
+ public boolean hasProcess(String name)
+ {
+ for (Process iter : _processList) {
+ if (iter.getName().equals(name))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Return a description of the processor.
+ *
+ * @return a description of the processor.
+ */
+ public String toString() {
+ return "Processor: " + getName() ;
+ }
+
+ /**
+ * Range of the iterator when the instance belongs to an iterated
+ * series of processors.
+ */
+ protected String _range;
+ protected String _type;
+
+ /**
+ * List of processes bound to this processor.
+ */
+ protected Vector<Process> _processList;
+}
--- /dev/null
+/* $Id: ReadPath.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Vector;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class defines a read path. A read path contains one processor,
+ * one rxbuf, one channel buf, and one or more hw channels.
+ */
+public class ReadPath extends ArchiResource {
+ /**
+ * Constructor to create an architecture connection with a name.
+ *
+ */
+ public ReadPath(String name) {
+ super(name);
+ _hwChannelList = new Vector<HWChannel>();
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this architectural connection.
+ *
+ * @return a new instance of the architectural connection.
+ */
+ /*
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ ReadPath newObj = (ReadPath) super.clone();
+ newObj.setProcessor(_processor);
+ newObj.setRXBuf(_rxBuf);
+ newObj.setCHBuf(_chBuf);
+ newObj.setHWChannelNameList((Vector)_hwChannelNameList.clone());
+ return (newObj);
+ }
+ */
+
+ /**
+ * Return a string representation of the architectural connection.
+ *
+ * @return string representation of the architectural connection
+ */
+ public String toString() {
+ return "ReadPath: " + getName();
+ }
+
+ /**
+ * Return the memory where the receive buffer is located.
+ *
+ * @return name of memory
+ */
+ public Memory getRXBuf() { return _rxBuf; }
+
+ /**
+ * Set the receive buffer location.
+ *
+ * @param rxbuf rxbuf location
+ */
+ public void setRXBuf(Memory rxbuf) { _rxBuf = rxbuf; }
+
+ /**
+ * Return the memory where the channel buffer is located.
+ *
+ * @return channel buffer location
+ */
+ public Memory getCHBuf() { return _chBuf; }
+
+ /**
+ * Set the channel buffer location
+ *
+ * @param chbuf memory where channel buffer is located.
+ */
+ public void setCHBuf(Memory chbuf) { _chBuf = chbuf; }
+
+ /**
+ * Return the list of the HW channels.
+ *
+ * @return list of HW channels
+ */
+ public Vector<HWChannel> getHWChannelList() { return _hwChannelList; }
+
+ /**
+ * Return the processor to which this path is associated.
+ *
+ * @return processor
+ */
+ public Processor getProcessor() {
+ return _processor;
+ }
+
+ /**
+ * Set the processor to which this path is associated
+ *
+ * @param processor processor
+ */
+ public void setProcessor(Processor processor) {
+ _processor = processor;
+ }
+
+
+ protected Processor _processor;
+ protected Memory _rxBuf;
+ protected Memory _chBuf;
+ protected Vector<HWChannel> _hwChannelList;
+}
--- /dev/null
+/* $Id: Variable.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class represents a global variable in the architecture XML.
+ */
+public class Variable implements Cloneable {
+
+ /**
+ * Constructor to create a Variable.
+ */
+ public Variable(String name) {
+ _name = name;
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Variable.
+ *
+ * @return new instance of the Variable.
+ */
+ public Object clone() {
+ try {
+ Variable newObj = (Variable) super.clone();
+ newObj.setName(_name);
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the value of the Variable.
+ *
+ * @return the value of the variable
+ */
+ public int getValue() {
+ return _value;
+ }
+
+ /**
+ * Set the value of the Variable.
+ *
+ * @param value the value of the variable
+ */
+ public void setValue(int value) {
+ _value = value;
+ }
+
+ /**
+ * Get the name of this SourceCode.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this SourceCode.
+ *
+ * @param name name of the SourceCode
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the parent ArchiResource.
+ *
+ * @return parent ArchiResource
+ */
+ public ArchiResource getParentResource() {
+ return _parentResource;
+ }
+
+ /**
+ * Set the parent ArchiResource.
+ *
+ * @param parentResource new parent
+ */
+ public void setParentResource(ArchiResource parentResource) {
+ _parentResource = parentResource;
+ }
+
+ /**
+ * Return a string representation of the Variable.
+ *
+ * @return string representation of the Variable
+ */
+ public String toString() {
+ return "Variable: " + getName();
+ }
+
+ protected int _value;
+ protected String _name = null;
+ protected ArchiResource _parentResource = null;
+}
--- /dev/null
+/* $Id: WritePath.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.architecture;
+
+import java.util.Vector;
+
+import dol.visitor.ArchiVisitor;
+
+/**
+ * This class defines a write path. A write path contains one processor,
+ * one txbuf, one channel buf, and one or more hw channels.
+ */
+public class WritePath extends ArchiResource {
+ /**
+ * Constructor to create an architecture connection with a name.
+ */
+ public WritePath(String name) {
+ super(name);
+ _hwChannelList = new Vector<HWChannel>();
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(ArchiVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this architectural connection.
+ *
+ * @return a new instance of the architectural connection.
+ */
+ /*
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ WritePath newObj = (WritePath) super.clone();
+ newObj.setProcessor(_processor);
+ newObj.setTXBuf(_txBuf);
+ newObj.setCHBuf(_chBuf);
+ newObj.setHWChannelNameList((Vector)_hwChannelNameList.clone());
+ return (newObj);
+ }
+ */
+
+ /**
+ * Return a string representation of the architectural connection.
+ *
+ * @return string representation of the architectural connection
+ */
+ public String toString() {
+ return "WritePath: " + getName();
+ }
+
+ /**
+ * Return the memory where the transmit buffer is located.
+ *
+ * @return name of memory
+ */
+ public Memory getTXBuf() { return _txBuf; }
+
+ /**
+ * Set the transmit buffer location.
+ *
+ * @param txbuf txbuf location
+ */
+ public void setTXBuf(Memory txbuf) { _txBuf = txbuf; }
+
+ /**
+ * Return the memory where the channel buffer is located.
+ *
+ * @return channel buffer location
+ */
+ public Memory getCHBuf() { return _chBuf; }
+
+ /**
+ * Set the channel buffer location
+ *
+ * @param chbuf memory where channel buffer is located.
+ */
+ public void setCHBuf(Memory chbuf) { _chBuf = chbuf; }
+
+ /**
+ * Return the list of the HW channels.
+ *
+ * @return list of HW channels
+ */
+ public Vector<HWChannel> getHWChannelList() { return _hwChannelList; }
+
+ /**
+ * Return the processor to which this path is associated.
+ *
+ * @return processor
+ */
+ public Processor getProcessor() {
+ return _processor;
+ }
+
+ /**
+ * Set the processor to which this path is associated.
+ *
+ * @param processor processor
+ */
+ public void setProcessor(Processor processor) {
+ _processor = processor;
+ }
+
+ protected Processor _processor;
+ protected Memory _txBuf;
+ protected Memory _chBuf;
+ protected Vector<HWChannel> _hwChannelList;
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Internal data model for the architecture representation.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+package dol.datamodel.mapping;
+
+import dol.visitor.MapVisitor;
+
+/**
+ * This class represents a binding element in the mapping.
+ */
+abstract public class Binding extends MapResource {
+
+ /**
+ * Constructor to create a Binding with a name.
+ */
+ public Binding(String name) {
+ super(name);
+ }
+
+ /**
+ * Accept a Visitor
+ * @param x A Visitor Object.
+ */
+ public void accept(MapVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Binding
+ *
+ * @return a new instance of the Binding.
+ */
+ public Object clone() {
+ Binding newObj = (Binding) super.clone();
+ return (newObj);
+ }
+
+ /**
+ * Get the range of this binding.
+ *
+ * @return range
+ */
+ public String getRange() {
+ return _range;
+ }
+
+ /**
+ * Set the range of this binding.
+ *
+ * @param range new range value
+ */
+ public void setRange(String range) {
+ _range= range;
+ }
+
+ /**
+ * Get the type of this binding.
+ *
+ * @return type
+ */
+ public String getType() {
+ return _type;
+ }
+
+ /**
+ * Return a description of the binding.
+ *
+ * @return a description of the binding.
+ */
+ public String toString() {
+ return "Binding: " + getName() ;
+ }
+
+ /**
+ * Range of the iterator when the instance belongs to an iterated
+ * series of bindings.
+ */
+ protected String _range;
+ protected String _type;
+
+ /**
+ * Type specifier for communication bindings.
+ */
+ public static final String COMMUNICATION = "communication";
+
+ /**
+ * Type specifier for computation bindings.
+ */
+ public static final String COMPUTATION = "computation";
+}
--- /dev/null
+/* $Id: CommunicationBinding.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.datamodel.mapping;\r
+\r
+import dol.datamodel.architecture.ReadPath;\r
+import dol.datamodel.architecture.WritePath;\r
+import dol.datamodel.pn.Channel;\r
+import dol.visitor.MapVisitor;\r
+\r
+/**\r
+ * This class represents a communication binding element in the mapping.\r
+ */\r
+public class CommunicationBinding extends Binding {\r
+\r
+ /**\r
+ * Constructor to create a CommunicationBinding with a name.\r
+ */\r
+ public CommunicationBinding(String name) {\r
+ super(name);\r
+ _type = COMMUNICATION;\r
+ }\r
+\r
+ /**\r
+ * Clone this Binding\r
+ *\r
+ * @return a new instance of the Binding.\r
+ */\r
+ public Object clone() {\r
+ CommunicationBinding newObj = (CommunicationBinding) super.clone();\r
+ newObj.setChannel(_channel);\r
+ newObj.setReadPath(_readPath);\r
+ newObj.setWritePath(_writePath);\r
+ return (newObj);\r
+ }\r
+\r
+ /**\r
+ * Accept a Visitor\r
+ *\r
+ * @param x visitor object\r
+ */\r
+ public void accept(MapVisitor x) {\r
+ x.visitComponent(this);\r
+ }\r
+\r
+ /** Set the SW channel */\r
+ public void setChannel(Channel c) {\r
+ _channel = c;\r
+ }\r
+\r
+ /** Get the SW channel */\r
+ public Channel getChannel() {\r
+ return _channel;\r
+ }\r
+\r
+ /** Set the read path */\r
+ public void setReadPath(ReadPath p) {\r
+ _readPath = p;\r
+ }\r
+\r
+ /** Get the read path */\r
+ public ReadPath getReadPath() {\r
+ return _readPath;\r
+ }\r
+\r
+ /** Set the write path */\r
+ public void setWritePath(WritePath p) {\r
+ _writePath = p;\r
+ }\r
+\r
+ /** Get the write path */\r
+ public WritePath getWritePath() {\r
+ return _writePath;\r
+ }\r
+\r
+ /**\r
+ * Return a description of the binding.\r
+ *\r
+ * @return a description of the binding.\r
+ */\r
+ public String toString() {\r
+ return "CommunicationBinding: " + getName() ;\r
+ }\r
+\r
+ private Channel _channel = null;\r
+\r
+ private ReadPath _readPath = null;\r
+\r
+ private WritePath _writePath = null;\r
+\r
+}\r
--- /dev/null
+/* $Id: ComputationBinding.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.datamodel.mapping;\r
+\r
+import dol.datamodel.architecture.Processor;\r
+import dol.datamodel.pn.Process;\r
+import dol.visitor.MapVisitor;\r
+\r
+/**\r
+ * This class represents a computation binding element in the mapping.\r
+ */\r
+public class ComputationBinding extends Binding {\r
+\r
+ /**\r
+ * Constructor to create a ComputationBinding with a name.\r
+ */\r
+ public ComputationBinding(String name) {\r
+ super(name);\r
+ _type = COMPUTATION;\r
+ }\r
+\r
+ /**\r
+ * Clone this Binding\r
+ *\r
+ * @return a new instance of the Binding.\r
+ */\r
+ public Object clone() {\r
+ ComputationBinding newObj = (ComputationBinding) super.clone();\r
+ newObj.setProcessor(_processor);\r
+ newObj.setProcess(_process);\r
+ return (newObj);\r
+ }\r
+\r
+ /**\r
+ * Accept a Visitor\r
+ *\r
+ * @param x visitor object\r
+ */\r
+ public void accept(MapVisitor x) {\r
+ x.visitComponent(this);\r
+ }\r
+\r
+ /** Set the PN process */\r
+ public void setProcess(Process p) {\r
+ _process = p;\r
+ }\r
+\r
+ /** Get the PN process */\r
+ public Process getProcess() {\r
+ return _process;\r
+ }\r
+\r
+ /** Set the processor from the architecture */\r
+ public void setProcessor(Processor p) {\r
+ _processor = p;\r
+ }\r
+\r
+ /** Get the processor */\r
+ public Processor getProcessor() {\r
+ return _processor;\r
+ }\r
+\r
+ /**\r
+ * Return a description of the binding.\r
+ *\r
+ * @return a description of the binding.\r
+ */\r
+ public String toString() {\r
+ return "ComputationBinding: " + getName() ;\r
+ }\r
+\r
+ private Process _process = null;\r
+\r
+ private Processor _processor = null;\r
+\r
+}\r
--- /dev/null
+/* $Id: Configuration.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.datamodel.mapping;\r
+\r
+import dol.visitor.MapVisitor;\r
+\r
+/**\r
+ * This class represents a name-value pair of a configuration tag in XML.\r
+ */\r
+public class Configuration {\r
+\r
+ /**\r
+ * Constructor to create a Configuration.\r
+ */\r
+ public Configuration(String name, String value) {\r
+ _name = name;\r
+ _value = value;\r
+ }\r
+\r
+ /**\r
+ * Accept a Visitor.\r
+ *\r
+ * @param x visitor object\r
+ */\r
+ public void accept(MapVisitor x) {\r
+ x.visitComponent(this);\r
+ }\r
+\r
+ /**\r
+ * Clone this Configuration.\r
+ *\r
+ * @return new instance of the Configuration.\r
+ */\r
+ public Object clone() {\r
+ try {\r
+ Configuration newObj = (Configuration) super.clone();\r
+ newObj._name = _name;\r
+ newObj._value = _value;\r
+ return (newObj);\r
+ } catch (CloneNotSupportedException e) {\r
+ System.out.println("Error Clone not Supported");\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Get the value of the Configuration.\r
+ *\r
+ * @return the value of the configuration.\r
+ */\r
+ public String getValue() {\r
+ return _value;\r
+ }\r
+\r
+ /**\r
+ * Get the name of this configuration.\r
+ *\r
+ * @return the name\r
+ */\r
+ public String getName() {\r
+ return _name;\r
+ }\r
+\r
+ /**\r
+ * Return a string representation of the Configuration.\r
+ *\r
+ * @return string representation of the Configuration\r
+ */\r
+ public String toString() {\r
+ return "Configuration: " + _name + "/" + _value;\r
+ }\r
+\r
+ protected String _value = null;\r
+ protected String _name = null;\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package dol.datamodel.mapping;
+
+import dol.visitor.MapVisitor;
+
+/**
+ * This class is the basic class which abstracts a mapping resource.
+ */
+public class MapResource implements Cloneable {
+ /**
+ * Constructor to create a mapping resource with a name.
+ */
+ public MapResource(String name) {
+ _name = name;
+ _basename = name;
+ }
+
+ /**
+ * Accept a Visitor
+ *
+ * @param x visitor object
+ */
+ public void accept(MapVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this mapping resource.
+ *
+ * @return new instance of the mapping resource.
+ */
+ public Object clone() {
+ try {
+ MapResource newObj = (MapResource) super.clone();
+ newObj.setName(_name);
+ newObj.setBasename(_basename);
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the name of this mapping resource.
+ *
+ * @return name of the mapping resource
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this mapping resource.
+ *
+ * @param name name of the mapping resource
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the basename of this mapping resource.
+ *
+ * @return basename of the mapping resource
+ */
+ public String getBasename() {
+ return _basename;
+ }
+
+ /**
+ * Set the basename of this mapping resource.
+ *
+ * @param basename name of the mapping resource
+ */
+ public void setBasename(String basename) {
+ _basename = basename;
+ }
+
+ /**
+ * Get the hierarchical parent of this mapping resource.
+ *
+ * @return parent of this mapping resource
+ */
+ public MapResource getParentResource() {
+ return _parentResource;
+ }
+
+ /**
+ * Set the hierarchical parent of this mapping resource.
+ *
+ * @param parentResource new parent
+ */
+ public void setParentResource(MapResource parentResource) {
+ _parentResource = parentResource;
+ }
+
+ /**
+ * Return a string representation of the architectural resource.
+ *
+ * @return string representation of the architectural resource
+ */
+ public String toString() {
+ return "MapResource: " + _name;
+ }
+
+ /** name of the architectural resource */
+ protected String _name = null;
+
+ /** basename of the architectural resource, if no basename, store the name */
+ protected String _basename = null;
+
+ /**
+ * parent resource of this architectural resource in a hierarchical architecture network
+ */
+ protected MapResource _parentResource = null;
+}
--- /dev/null
+package dol.datamodel.mapping;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.MapVisitor;
+
+
+/**
+ * This class defines a mapping.
+ */
+public class Mapping extends MapResource
+{
+ public Mapping(String name)
+ {
+ super(name);
+ _compBindList = new Vector<ComputationBinding>();
+ _commBindList = new Vector<CommunicationBinding>();
+ _scheduleList = new Vector<Schedule>();
+ _variableList = new Vector<Variable>();
+ /**
+ * For some code generation back end, traversing via architecture
+ * model rather than mapping model is more convenient, since the
+ * mapping model is a flattened view of the binding where one can
+ * not access all the binded processes from a processor. Therefore
+ * we annotate the binding information back to processor.
+ */
+ _processList = new Vector<Process>();
+ _processorList = new Vector<Processor>();
+ }
+
+ /**
+ * Accept a visitor
+ *
+ * @param x visitor object
+ */
+ public void accept(MapVisitor x) {
+ x.visitComponent(this);
+ }
+
+
+ /**
+ * Clone this Mapping.
+ *
+ * @return new instance of the Mapping
+ */
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ Mapping newObj = (Mapping) super.clone();
+ newObj.setCompBindList((Vector<ComputationBinding>)_compBindList.clone());
+ newObj.setCommBindList((Vector<CommunicationBinding>)_commBindList.clone());
+ newObj.setScheduleList((Vector<Schedule>)_scheduleList.clone());
+ newObj.setVarList((Vector<Variable>)_variableList.clone());
+ newObj.setProcessorList((Vector<Processor>)_processorList.clone());
+ newObj.setProcessList((Vector<Process>)_processList.clone());
+ return (newObj);
+ }
+
+ /** Get the process network. */
+ public ProcessNetwork getPN() { return _pn; }
+
+ /** Store a reference to the process network. */
+ public void setPN(ProcessNetwork pn) { _pn = pn; }
+
+ /** Get the architecture */
+ public Architecture getArch() { return _arch; }
+
+ /** Store a reference to the architecture. */
+ public void setArch(Architecture arch) { _arch = arch; }
+
+ /**
+ * Get a list of computation bindings in this Mapping.
+ *
+ * @return the binding list
+ */
+ public Vector<ComputationBinding> getCompBindList() {
+ return _compBindList;
+ }
+
+ /**
+ * Get a list of processes in this Mapping.
+ *
+ * @return the process list
+ */
+ public Vector<Process> getProcessList() {
+ return _processList;
+ }
+
+ /**
+ * Return a process which has a specific name. Return null if
+ * process cannot be found.
+ *
+ * @param name the name of the process to search for.
+ * @return the process with the specific name or null if not found.
+ */
+ public Process getProcess(String name)
+ {
+ for (Process process : _processList) {
+ if (process.getName().equals(name)) {
+ return process;
+ }
+ }
+ return null;
+ }
+ /**
+ * Set the computation binding list of this mapping.
+ *
+ * @param compBindList The new list
+ */
+ public void setCompBindList( Vector<ComputationBinding> compBindList ) {
+ _compBindList = compBindList;
+ }
+
+ /**
+ * Get a list of communication bindings in this Mapping.
+ *
+ * @return the binding list
+ */
+ public Vector<CommunicationBinding> getCommBindList() {
+ return _commBindList;
+ }
+
+ /**
+ * Set the communication binding list of this mapping.
+ *
+ * @param commBindList The new list
+ */
+ public void setCommBindList( Vector<CommunicationBinding> commBindList ) {
+ _commBindList = commBindList;
+ }
+
+ /**
+ * Set the process list of this mapping.
+ *
+ * @param processList The new list
+ */
+ public void setProcessList( Vector<Process> processList ) {
+ _processList = processList;
+ }
+
+ /**
+ * Get the a list of processors in this Mapping.
+ *
+ * @return the processor list
+ */
+ public Vector<Processor> getProcessorList() {
+ return _processorList;
+ }
+
+ /**
+ * Set the processor list of this mapping.
+ *
+ * @param processorList The new list
+ */
+ public void setProcessorList( Vector<Processor> processorList ) {
+ _processorList = processorList;
+ }
+
+ /**
+ * Return a processor which has a specific name. Return null if
+ * processor cannot be found.
+ *
+ * @param name the name of the processor to search for.
+ * @return the processor with the specific name or null if not found.
+ */
+ public Processor getProcessor(String name)
+ {
+ Iterator<Processor> i;
+ i = _processorList.iterator();
+ while (i.hasNext()) {
+ Processor processor = i.next();
+ if (processor.getName().equals(name)) {
+ return processor;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the a list of schedules in this Mapping.
+ *
+ * @return the schedule list
+ */
+ public Vector<Schedule> getScheduleList() {
+ return _scheduleList;
+ }
+
+ /**
+ * Set the schedule list of this mapping.
+ *
+ * @param scheduleList The new list
+ */
+ public void setScheduleList( Vector<Schedule> scheduleList ) {
+ _scheduleList = scheduleList;
+ }
+
+ /**
+ * Return the schedule for a resource that has a specific name.
+ * Return null if schedule cannot be found.
+ *
+ * @param name the name of the resource for which we are looking for the schedule.
+ * @return the schedule for the resource with the specified name.
+ */
+ public Schedule getScheduleByResource(String name) {
+ for(Schedule schedule : _scheduleList) {
+ if (schedule.getResource().getName().equals(name)) {
+ return schedule;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the communication binding for a channel that has a specific name.
+ * Return null if binding cannot be found.
+ *
+ * @param name the name of the channel for which we are looking for the binding.
+ * @return the binding for the channel with the specified name.
+ */
+ public CommunicationBinding getCommBindingByChannel(String name) {
+ for(CommunicationBinding b : _commBindList) {
+ if (b.getChannel().getName().equals(name)) {
+ return b;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the variable list of a Mapping.
+ *
+ * @return the variable list
+ */
+ public Vector<Variable> getVarList() {
+ return _variableList;
+ }
+
+ /**
+ * Set the variable list of a mapping.
+ *
+ * @param variableList The new list
+ */
+ public void setVarList( Vector<Variable> variableList ) {
+ _variableList = variableList;
+ }
+
+ /** ProcessNetwork Reference **/
+ protected ProcessNetwork _pn = null;
+
+ /** Architecture Reference **/
+ protected Architecture _arch = null;
+
+ /** List of processes in the mapping **/
+ protected Vector<Process> _processList = null;
+
+ /** List of processors actually used in the mapping **/
+ protected Vector<Processor> _processorList = null;
+
+ /** List of computations bindings in the mapping **/
+ protected Vector<ComputationBinding> _compBindList = null;
+
+ /** List of communication bindings in the mapping **/
+ protected Vector<CommunicationBinding> _commBindList = null;
+
+ /** List of schedules in the mapping **/
+ protected Vector<Schedule> _scheduleList = null;
+
+ /** List of variables in the mapping **/
+ protected Vector<Variable> _variableList = null;
+}
--- /dev/null
+/* $Id: Schedule.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.datamodel.mapping;\r
+\r
+import java.util.Vector;\r
+\r
+import dol.datamodel.architecture.ArchiResource;\r
+import dol.visitor.MapVisitor;\r
+\r
+/**\r
+ * This class represents a schedule element in the mapping.\r
+ */\r
+public class Schedule extends MapResource {\r
+\r
+ /**\r
+ * Constructor to create a Schedule with a name.\r
+ */\r
+ public Schedule(String name) {\r
+ super(name);\r
+ _entryList = new Vector<ScheduleEntry>();\r
+ _cfgList = new Vector<Configuration>();\r
+ }\r
+\r
+ /**\r
+ * Accept a Visitor\r
+ *\r
+ * @param x visitor object\r
+ */\r
+ public void accept(MapVisitor x) {\r
+ x.visitComponent(this);\r
+ }\r
+\r
+ /**\r
+ * Clone this Schedule resource.\r
+ *\r
+ * @return new instance of the Schedule resource.\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public Object clone() {\r
+ Schedule newObj = (Schedule) super.clone();\r
+ newObj.setResource(_resource);\r
+ newObj.setSchedPolicy(_policy);\r
+ newObj.setCfgList((Vector<Configuration>)_cfgList.clone() );\r
+ newObj.setEntryList((Vector<ScheduleEntry>)_entryList.clone());\r
+ return (newObj);\r
+ }\r
+\r
+ /** Set the resource, a HW channel or a processor from the architecture */\r
+ public void setResource(ArchiResource r) {\r
+ _resource = r;\r
+ }\r
+\r
+ /** Get the resource */\r
+ public ArchiResource getResource() {\r
+ return _resource;\r
+ }\r
+\r
+ /** Set the scheduling policy */\r
+ public void setSchedPolicy(SchedulingPolicy p) {\r
+ _policy = p;\r
+ }\r
+\r
+ /** Get the scheduling policy */\r
+ public SchedulingPolicy getSchedPolicy() {\r
+ return _policy;\r
+ }\r
+\r
+ /**\r
+ * Get the list of configurations of this schedule.\r
+ *\r
+ * @return list of configurations\r
+ */\r
+ public Vector<Configuration> getCfgList() {\r
+ return _cfgList;\r
+ }\r
+\r
+ /**\r
+ * Set the list of configurations of this schedule.\r
+ *\r
+ * @param cfgList configuration list\r
+ */\r
+ public void setCfgList(Vector<Configuration> cfgList) {\r
+ _cfgList = cfgList;\r
+ }\r
+\r
+ /**\r
+ * Set the list of scheduler table entries.\r
+ *\r
+ * @param entryList The new list\r
+ */\r
+ public void setEntryList(Vector<ScheduleEntry> entryList) {\r
+ _entryList = entryList;\r
+ }\r
+\r
+ /** Get the list of scheduler table entries */\r
+ public Vector<ScheduleEntry> getEntryList() {\r
+ return _entryList;\r
+ }\r
+\r
+ /**\r
+ * Return the scheduler table entry with its schedule configuration \r
+ * that has a specific name.\r
+ * Return null if the entry cannot be found.\r
+ *\r
+ * @param name the name of the entry for which we are looking for.\r
+ * @return the entry with its schedule configuration with the specified name.\r
+ */\r
+ public ScheduleEntry getScheduleEntry(String name) {\r
+ for(ScheduleEntry entry : _entryList) {\r
+ if (entry.getName().equals(name)) {\r
+ return entry;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Return the value for the given configuration key. Return null\r
+ * when the key cannot be found.\r
+ *\r
+ * @param name name of the configuration key to search for\r
+ * @return value of the specified configuration key\r
+ */\r
+ public String getCfgValue(String name) {\r
+ for(Configuration c : _cfgList) {\r
+ if(c.getName().equals(name)) {\r
+ return c.getValue();\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Return a string representation of the Schedule.\r
+ *\r
+ * @return string representation of the Schedule\r
+ */\r
+ public String toString() {\r
+ return "Schedule: " + getName();\r
+ }\r
+\r
+ /** Resource that is scheduled */\r
+ ArchiResource _resource = null;\r
+\r
+ /** Scheduling policy */\r
+ SchedulingPolicy _policy = null;\r
+\r
+ /** List of the configurations of the Schedule */\r
+ protected Vector<Configuration> _cfgList = null;\r
+\r
+ /** List of scheduler table entries */\r
+ Vector<ScheduleEntry> _entryList = null;\r
+\r
+ /** Configuration key for the slots per cycle of a TDMA scheduler */\r
+ final public static String cfdTdmaSlotsPerCycle = "slotsonecycle";\r
+\r
+ /** Configuration key for the general slot length\r
+ * in nanoseconds of a TDMA scheduler */\r
+ final public static String cfgTdmaSlotLength = "slotlength";\r
+\r
+}\r
--- /dev/null
+/* $Id: ScheduleEntry.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.datamodel.mapping;\r
+\r
+import java.util.Vector;\r
+\r
+import dol.datamodel.pn.Schedulable;\r
+import dol.visitor.MapVisitor;\r
+\r
+/**\r
+ * This class represents an origin element in the mapping which refers\r
+ * to a PN process or a SW channel with a configuration element.\r
+ */\r
+public class ScheduleEntry extends MapResource {\r
+\r
+ /**\r
+ * Constructor to create a ScheduleProcess with a name.\r
+ */\r
+ public ScheduleEntry(String name) {\r
+ super(name);\r
+ _cfgList = new Vector<Configuration>();\r
+ }\r
+\r
+ /**\r
+ * Accept a Visitor\r
+ *\r
+ * @param x visitor object\r
+ */\r
+ public void accept(MapVisitor x) {\r
+ x.visitComponent(this);\r
+ }\r
+\r
+ /**\r
+ * Clone this ScheduleProcess resource.\r
+ *\r
+ * @return new instance of the ScheduleProcess resource.\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public Object clone() {\r
+ ScheduleEntry newObj = (ScheduleEntry) super.clone();\r
+ newObj.setConsumer(_consumer);\r
+ newObj.setCfgList((Vector<Configuration>)_cfgList.clone());\r
+ return (newObj);\r
+ }\r
+\r
+ /**\r
+ * Get the list of configurations of this scheduled process.\r
+ *\r
+ * @return list of configurations\r
+ */\r
+ public Vector<Configuration> getCfgList() {\r
+ return _cfgList;\r
+ }\r
+\r
+ /**\r
+ * Set the list of configurations of this scheduled process.\r
+ *\r
+ * @param cfgList configuration list\r
+ */\r
+ public void setCfgList(Vector<Configuration> cfgList) {\r
+ _cfgList = cfgList;\r
+ }\r
+\r
+ /** Set the consumer */\r
+ public void setConsumer(Schedulable c) {\r
+ _consumer = c;\r
+ }\r
+\r
+ /** Get the consumer */\r
+ public Schedulable getConsumer() {\r
+ return _consumer;\r
+ }\r
+\r
+ /**\r
+ * Return the value for the given configuration key. Return null\r
+ * when the key cannot be found.\r
+ *\r
+ * @param name name of the configuration key to search for\r
+ * @return value of the specified configuration key\r
+ */\r
+ public String getCfgValue(String name) {\r
+ for(Configuration c : _cfgList) {\r
+ if(c.getName().equals(name)) {\r
+ return c.getValue();\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Return a string representation of the ScheduleProcess.\r
+ *\r
+ * @return string representation of the ScheduleProcess\r
+ */\r
+ public String toString() {\r
+ return "ScheduleProcess: " + getName();\r
+ }\r
+\r
+ /** Consumer: PN process or SW channel */\r
+ private Schedulable _consumer = null;\r
+\r
+ /** list of the configurations of the ScheduleProcess */\r
+ protected Vector<Configuration> _cfgList = null;\r
+\r
+ /** Configuration key for the priority of a task in a fixed priority scheduler */\r
+ final public static String cfgFpPriority = "priority";\r
+\r
+ /** Configuration key for the index of the TDMA slot of a process */\r
+ final public static String cfgTdmaStartSlot = "startslot";\r
+\r
+ /** Configuration key for the number of TDMA slots for a process */\r
+ final public static String cfgTdmaNumberOfSlots = "numberofslots";\r
+\r
+}\r
--- /dev/null
+/* $Id: SchedulingPolicy.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.datamodel.mapping;\r
+\r
+/**\r
+ * This class defines the supported scheduling policies.\r
+ */\r
+public enum SchedulingPolicy {\r
+\r
+ STATIC, FIXEDPRIORITY, FIFO, TDMA, ROUNDROBIN;\r
+\r
+ private static final String staticVal = "static";\r
+ private static final String fixedPriorityVal = "fixedpriority";\r
+ private static final String fifoVal = "fifo";\r
+ private static final String tdmaVal = "tdma";\r
+ private static final String roundRobinVal = "roundrobin";\r
+\r
+ static public SchedulingPolicy fromString(String s) {\r
+ if(s.equals(staticVal)) {\r
+ return SchedulingPolicy.STATIC;\r
+ } else if(s.equals(fixedPriorityVal)) {\r
+ return SchedulingPolicy.FIXEDPRIORITY;\r
+ } else if(s.equals(fifoVal)) {\r
+ return SchedulingPolicy.FIFO;\r
+ } else if(s.equals(tdmaVal)) {\r
+ return SchedulingPolicy.TDMA;\r
+ }\r
+ return SchedulingPolicy.ROUNDROBIN;\r
+ }\r
+\r
+ static public String toString(SchedulingPolicy t) {\r
+ if(t == SchedulingPolicy.STATIC) {\r
+ return staticVal;\r
+ } else if(t == SchedulingPolicy.FIXEDPRIORITY) {\r
+ return fixedPriorityVal;\r
+ } else if(t == SchedulingPolicy.FIFO) {\r
+ return fifoVal;\r
+ } else if(t == SchedulingPolicy.TDMA) {\r
+ return tdmaVal;\r
+ }\r
+ return roundRobinVal;\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+package dol.datamodel.mapping;
+
+import dol.visitor.MapVisitor;
+
+/**
+ * This class represents a global variable in the mapping XML.
+ */
+public class Variable implements Cloneable {
+
+ /**
+ * Constructor to create a Variable.
+ */
+ public Variable(String name) {
+ _name = name;
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(MapVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Variable.
+ *
+ * @return new instance of the Variable.
+ */
+ public Object clone() {
+ try {
+ Variable newObj = (Variable) super.clone();
+ newObj.setName(_name);
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the value of the Variable.
+ *
+ * @return the value of the variable
+ */
+ public int getValue() {
+ return _value;
+ }
+
+ /**
+ * Set the value of the Variable.
+ *
+ * @param value the value of the variable
+ */
+ public void setValue(int value) {
+ _value = value;
+ }
+
+ /**
+ * Get the name of this SourceCode.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this SourceCode.
+ *
+ * @param name name of the SourceCode
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the parent ArchiResource.
+ *
+ * @return parent ArchiResource
+ */
+ public MapResource getParentResource() {
+ return _parentResource;
+ }
+
+ /**
+ * Set the parent ArchiResource.
+ *
+ * @param parentResource new parent
+ */
+ public void setParentResource(MapResource parentResource) {
+ _parentResource = parentResource;
+ }
+
+ /**
+ * Return a string representation of the Variable.
+ *
+ * @return string representation of the Variable
+ */
+ public String toString() {
+ return "Variable: " + getName();
+ }
+
+ protected int _value;
+ protected String _name = null;
+ protected MapResource _parentResource = null;
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Internal data model for the mapping representation.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Internal data model.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: Channel.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is the basic channel in a process network.
+ * The channel has a name and a list of ports connected by this channel.
+ * In this model, a channel has only two ports: one input port and one
+ * output port.
+ */
+public class Channel extends Resource implements Schedulable {
+
+ /**
+ * Constructor to create a channel with a name and an empty
+ * portList.
+ */
+ public Channel(String name) {
+ super(name);
+ }
+
+ /**
+ * Accept a visitor.
+ * @param x visitor object
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this channel.
+ *
+ * @return new instance of the channel
+ */
+ public Object clone() {
+ Channel newObj = (Channel) super.clone();
+ return (newObj);
+ }
+
+ /**
+ * Get the size of this channel.
+ *
+ * @return size of the channel
+ */
+ public int getSize() {
+ return _size;
+ }
+
+ /**
+ * Set the size of this channel.
+ *
+ * @param size new size value
+ */
+ public void setSize(int size) {
+ _size = size;
+ }
+
+ /**
+ * Get the token size of this channel.
+ *
+ * @return token size of the channel
+ */
+ public int getTokenSize() {
+ return _tokenSize;
+ }
+
+ /**
+ * Set the token size of this channel.
+ *
+ * @param size new token size
+ */
+ public void setTokenSize(int size) {
+ _tokenSize = size;
+ }
+
+ /**
+ * Return a string representation of the channel.
+ *
+ * @return string representation of the channel
+ */
+ public String toString() {
+ return "Channel: " + getName();
+ }
+
+ /**
+ * Get the process where this channel starts from.
+ *
+ * @return origin process
+ */
+ public Process getOrigin() {
+ return _origin;
+ }
+
+ /**
+ * Set the process where this channel starts from.
+ *
+ * @param origin origin process
+ */
+ public void setOrigin(Process origin) {
+ _origin = origin;
+ }
+
+ /**
+ * Get the process where this channel ends.
+ *
+ * @return target process
+ */
+ public Process getTarget() {
+ return _target;
+ }
+
+ /**
+ * Set the process where this channel ends.
+ *
+ * @param target target process
+ */
+ public void setTarget(Process target) {
+ _target = target;
+ }
+
+ protected Process _origin;
+ protected Process _target;
+
+ /** size of the channel */
+ protected int _size;
+
+ /** token size fo the channel */
+ protected int _tokenSize;
+}
--- /dev/null
+/* $Id: Configuration.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import dol.visitor.PNVisitor;
+
+/**
+ * This class represents a name-value pair of a configuration tag in XML.
+ */
+public class Configuration {
+
+ /**
+ * Constructor to create a Configuration.
+ */
+ public Configuration(String name) {
+ _name = name;
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Configuration.
+ *
+ * @return new instance of the Configuration.
+ */
+ public Object clone() {
+ try {
+ Configuration newObj = (Configuration) super.clone();
+ newObj.setName(_name);
+ newObj.setValue(_value);
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the value of the Configuration.
+ *
+ * @return the value of the configuration.
+ */
+ public String getValue() {
+ return _value;
+ }
+
+ /**
+ * Set the value of the Configuration.
+ *
+ * @param value the value of the configuration.
+ */
+ public void setValue(String value) {
+ _value = value;
+ }
+
+ /**
+ * Get the name of this configuration.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this configuration.
+ *
+ * @param name name of the configuration
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the hierarchical parent of this resource.
+ *
+ * @return parent of this resource
+ */
+ public Resource getParentResource() {
+ return _parentResource;
+ }
+
+
+ /**
+ * Set the hierarchical parent of this resource.
+ *
+ * @param parentResource new parent
+ */
+ public void setParentResource(Resource parentResource) {
+ _parentResource = parentResource;
+ }
+
+
+ /**
+ * Return a string representation of the Configuration.
+ *
+ * @return string representation of the Configuration
+ */
+ public String toString() {
+ return "Configuration: " + getName();
+ }
+
+ protected String _value = null;
+ protected String _name = null;
+ protected Resource _parentResource = null;
+}
--- /dev/null
+/* $Id: Connection.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import dol.visitor.PNVisitor;
+
+/**
+ * This class defines a connection.
+ * A connection contains one origin and one target resource and the
+ * according ports.
+ */
+public class Connection extends Resource {
+
+ /**
+ * Constructor to create a Connection with a name,
+ * empty process list and empty channel list.
+ */
+ public Connection(String name) {
+ super(name);
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Connection.
+ *
+ * @return a new instance of the Connection.
+ */
+ public Object clone() {
+ Connection newObj = (Connection) super.clone();
+ newObj.setOrigin(_origin);
+ newObj.setOriginPort(_originPort);
+ newObj.setTarget(_target);
+ newObj.setTargetPort(_targetPort);
+ return (newObj);
+ }
+
+ /**
+ * Return a string representation of the connection.
+ *
+ * @return string representation of the connection
+ */
+ public String toString() {
+ return "Connection: " + getName();
+ }
+
+
+ /**
+ * Get the origin resource of his connection.
+ *
+ * @return origin resource
+ */
+ public Resource getOrigin() {
+ return _origin;
+ }
+
+ /**
+ * Set the origin resource of this connection.
+ *
+ * @param origin origin resource
+ */
+ public void setOrigin(Resource origin) {
+ _origin = origin;
+ }
+
+ /**
+ * Get the origin port of this connection.
+ *
+ * @return origin port
+ */
+ public Port getOriginPort() {
+ return _originPort;
+ }
+
+ /**
+ * Set the origin port of this connection.
+ *
+ * @param port origin port
+ */
+ public void setOriginPort(Port port) {
+ _originPort = port;
+ }
+
+ /**
+ * Get the target resource of his connection.
+ *
+ * @return target resource
+ */
+ public Resource getTarget() {
+ return _target;
+ }
+
+ /**
+ * Set the target resource of this connection.
+ *
+ * @param target target resource
+ */
+ public void setTarget(Resource target) {
+ _target = target;
+ }
+
+ /**
+ * Get the target port of this connection.
+ *
+ * @return target port
+ */
+ public Port getTargetPort() {
+ return _targetPort;
+ }
+
+ /**
+ * Set the target port of this connection.
+ *
+ * @param port target port
+ */
+ public void setTargetPort(Port port) {
+ _targetPort = port;
+ }
+
+ protected Resource _origin;
+ protected Port _originPort;
+ protected Resource _target;
+ protected Port _targetPort;
+}
--- /dev/null
+/* $Id: Port.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import dol.visitor.PNVisitor;
+
+/**
+ * This class represents a port of a process or channel.
+ */
+public class Port {
+
+ /**
+ * Constructor to create a Port with a name.
+ */
+ public Port(String name) {
+ _name = name;
+ _isInPort = false;
+ _isOutPort = false;
+ }
+
+ public Port(String name, boolean type) {
+ _name = name;
+ _isInPort = (type == INPORT);
+ _isOutPort = (type == OUTPORT);
+ }
+
+
+ /**
+ * Accept a visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Port
+ *
+ * @return new instance of the Port
+ */
+ public Object clone() {
+ try {
+ Port newObj = (Port) super.clone();
+ newObj.setName(_name);
+ newObj.setBasename(_basename);
+ newObj.setPeerPort(_peerPort);
+ newObj.setPeerResource(_peerResource);
+ newObj.setResource(_resource );
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Check whether this port is an inport.
+ *
+ * @return true if this port is an inport, otherwise false
+ */
+ public boolean isInPort() {
+ return _isInPort;
+ }
+
+ /**
+ * Check whether this port is an outport.
+ *
+ * @return true if this port is an outport, otherwise false
+ */
+ public boolean isOutPort() {
+ return _isOutPort;
+ }
+
+ /**
+ * Get the name of this port.
+ *
+ * @return name of the port
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this port.
+ *
+ * @param name name of the port
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the range of this port.
+ *
+ * @return range of the port
+ */
+ public String getRange() {
+ return _range;
+ }
+
+ /**
+ * Set the range of this port.
+ *
+ * @param range range of the port
+ */
+ public void setRange(String range) {
+ _range= range;
+ }
+
+ /**
+ * Get the resource of this port.
+ *
+ * @return the resource
+ */
+ public Resource getResource() {
+ return _resource;
+ }
+
+ /**
+ * Set the process of this port.
+ *
+ * @param resource The new resource
+ */
+ public void setResource(Resource resource) {
+ _resource = resource;
+ }
+
+ public void setBasename(String basename) { _basename = basename; }
+ public String getBasename() { return _basename; }
+
+ // for channel port
+ public void setPeerPort(Port peer) { _peerPort = peer; }
+ public Port getPeerPort() { return _peerPort; }
+
+ // for process port: peer channel name
+ public void setPeerResource(Resource n) { _peerResource = n; }
+ public Resource getPeerResource() { return _peerResource; }
+
+ public String getType() {
+ if (_isInPort) return "input";
+ else if (_isOutPort) return "output";
+ else return "";
+ }
+
+ /**
+ * Return a string representation of the port.
+ *
+ * @return string representation of the port
+ */
+ public String toString() {
+ return "Port: " + _name;
+ }
+
+ /** constant for inport for usage in the constructor **/
+ public static final boolean INPORT = true;
+
+ /** constant for outport for usage in the constructor **/
+ public static final boolean OUTPORT = false;
+
+ /** defines whether this port is an inport **/
+ protected boolean _isInPort = false;
+
+ /** defines whether this port is an outport **/
+ protected boolean _isOutPort = false;
+
+ /** name of the port */
+ protected String _name = null;
+
+ /** basename of the resource, if no basename, store the name */
+ protected String _basename = null;
+
+ /** resource (process or channel) this port belongs to */
+ protected Resource _resource = null;
+
+ /** resource which peerPort belongs to */
+ protected Resource _peerResource = null;
+
+ /** connected peer port name */
+ protected Port _peerPort = null;
+
+ /** peer channel name */
+ protected String _channelName = null;
+
+ /**
+ * Range of the iterator when the instance belongs to an iterated
+ * series of ports.
+ */
+ protected String _range = "";
+}
--- /dev/null
+/* $Id: Process.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import dol.datamodel.architecture.Processor;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class represents a process.
+ */
+public class Process extends Resource implements Schedulable {
+
+ /**
+ * Constructor to create a Process with a name and an empty
+ * portList.
+ */
+ public Process(String name) {
+ super(name);
+ }
+
+ /**
+ * Accept a Visitor
+ * @param x A Visitor Object.
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Process
+ *
+ * @return a new instance of the Process.
+ */
+ public Object clone() {
+ Process newObj = (Process) super.clone();
+ newObj.setRange(_range);
+ newObj.setProcessor(_processor);
+ return (newObj);
+ }
+
+ /**
+ * Get the range of this process.
+ *
+ * @return range
+ */
+ public String getRange() {
+ return _range;
+ }
+
+ /**
+ * Get the iterator indices of this process.
+ *
+ * @return range
+ */
+ public Vector<Integer> getIteratorIndices() {
+ Vector<Integer> indices = new Vector<Integer>();
+ StringTokenizer tokenizer =
+ new StringTokenizer(_name.replaceAll(_basename, ""), "_");
+ while (tokenizer.hasMoreTokens()) {
+ indices.add(Integer.valueOf(tokenizer.nextToken()));
+ }
+ return indices;
+ }
+
+ /**
+ * Set the range of this process.
+ *
+ * @param range new range value
+ */
+ public void setRange(String range) {
+ _range= range;
+ }
+
+ public boolean hasInPorts() {
+ for (Port port : getPortList()) {
+ if (port.isInPort())
+ return true;
+ }
+ return false;
+ }
+
+ public boolean hasOutPorts() {
+ for (Port port : getPortList()) {
+ if (port.isOutPort())
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get number of inport
+ */
+ public int getNumOfInports() {
+ int i = 0;
+ for (Port port : getPortList())
+ if (port.isInPort())
+ i++;
+ return i;
+ }
+
+ /**
+ * Get number of outport
+ */
+ public int getNumOfOutports() {
+ int i = 0;
+ for (Port port : getPortList())
+ if (port.isOutPort())
+ i++;
+ return i;
+ }
+
+ /**
+ * Set the processor this process runs on.
+ * @param processor
+ */
+ public void setProcessor(Processor processor)
+ {
+ _processor = processor;
+ }
+
+ /**
+ * Get the processor this process runs on.
+ */
+ public Processor getProcessor()
+ {
+ return _processor;
+ }
+
+ /**
+ * Return a description of the process.
+ *
+ * @return a description of the process.
+ */
+ public String toString() {
+ return "Process: " + getName();
+ }
+
+ /**
+ * Range of the iterator when the instance belongs to an iterated
+ * series of processes.
+ */
+ protected String _range = "";
+
+ /**
+ * Processor that executes this process.
+ */
+ protected Processor _processor = null;
+}
--- /dev/null
+/* $Id: ProcessNetwork.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import java.util.Vector;
+
+import dol.visitor.PNVisitor;
+
+
+/**
+ * This class defines a process network.
+ */
+public class ProcessNetwork extends Resource {
+
+ /**
+ * Constructor to create a process network with a name,
+ * empty process list and empty channel list.
+ */
+ public ProcessNetwork(String name) {
+ super(name);
+ _processList = new Vector<Process>();
+ _channelList = new Vector<Channel>();
+ _varList = new Vector<Variable>();
+ _connectionList = new Vector<Connection>();
+ }
+
+ /**
+ * Accept a visitor
+ *
+ * @param x visitor object
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this ProcessNetwork.
+ *
+ * @return new instance of the ProcessNetwork
+ */
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ ProcessNetwork newObj = (ProcessNetwork) super.clone();
+ newObj.setProcessList((Vector<Process>)_processList.clone());
+ newObj.setChannelList((Vector<Channel>)_channelList.clone());
+ newObj.setVarList((Vector<Variable>)_varList.clone());
+ newObj.setConnectionList((Vector<Connection>)_connectionList.clone());
+ return (newObj);
+ }
+
+ /**
+ * Get the process list of a ProcessNetwork.
+ *
+ * @return the process list
+ */
+ public Vector<Process> getProcessList() {
+ return _processList;
+ }
+
+ /**
+ * Get the process basenames.
+ *
+ * @return process basenames
+ */
+ public Vector<String> getProcessBasenames() {
+ Vector<String> basenames = new Vector<String>();
+ for (Process p : _processList) {
+ String basename = p.getBasename();
+ if (!basenames.contains(basename)) {
+ basenames.add(basename);
+ }
+ }
+ return basenames;
+ }
+
+ /**
+ * Set the process list of a ProcessNetwork.
+ *
+ * @param processList The new list
+ */
+ public void setProcessList(Vector<Process> processList) {
+ _processList = processList;
+ }
+
+ /**
+ * Get the channel list of a ProcessNetwork
+ *
+ * @return the channel list
+ */
+ public Vector<Channel> getChannelList() {
+ return _channelList;
+ }
+
+ /**
+ * Set the channel list of a ProcessNetwork
+ *
+ * @param channelList The new list
+ */
+ public void setChannelList(Vector<Channel> channelList) {
+ _channelList = channelList;
+ }
+
+ public Vector<Variable> getVarList() { return _varList; }
+ public void setVarList(Vector<Variable> list) { _varList = list; }
+
+ public void setConnectionList(Vector<Connection> list) { _connectionList = list; }
+ public Vector<Connection> getConnectionList() { return _connectionList; }
+
+
+ /**
+ * Return a description of the ProcessNetwork.
+ *
+ * @return a description of the ProcessNetwork.
+ */
+ public String toString() {
+ return "ProcessNetwork: " + getName();
+ }
+
+ /**
+ * Return a process which has a specific name. Return null if
+ * process cannot be found.
+ *
+ * @param name the name of the process to search for.
+ * @return the process with the specific name.
+ */
+ public Process getProcess(String name) {
+ for (Process process : _processList) {
+ if (process.getName().equals(name)) {
+ return process;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return a channel which has a specific name. Return null if
+ * not found.
+ *
+ * @param name the name of the channel to search for.
+ * @return the channel with the specific name.
+ */
+ public Channel getChannel(String name) {
+ for (Channel c : _channelList) {
+ if (c.getName().equals(name)) {
+ return c;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * In this version, we only deal with the flattened process network.
+ * Connection infomation is filled to each process and channel for fast
+ * iteration.
+ */
+ public void fillPortPeerInfo() throws Exception {
+ for (Connection c : getConnectionList()) {
+ Port originPort = c.getOriginPort();
+ Port targetPort = c.getTargetPort();
+ originPort.setPeerResource(c.getTarget());
+ originPort.setPeerPort(targetPort);
+ targetPort.setPeerResource(c.getOrigin());
+ targetPort.setPeerPort(originPort);
+ }
+
+ //for each sw channel, determine which processes it connects
+ for (Connection c : getConnectionList()) {
+ if (c.getOrigin() instanceof Process) {
+ Channel channel = (Channel)c.getTarget();
+ channel.setOrigin((Process)c.getOrigin());
+ }
+ else if (c.getOrigin() instanceof Channel) {
+ Channel channel = (Channel)c.getOrigin();
+ channel.setTarget((Process)c.getTarget());
+ }
+ }
+ }
+
+ /** list of the processes in the ProcessNetwork. */
+ protected Vector<Process> _processList = null;
+
+ /** list of the channels in the ProcessNetwork. */
+ protected Vector<Channel> _channelList = null;
+
+ /** list of variables in the ProcessNetwork */
+ protected Vector<Variable> _varList = null;
+
+ /** list of connections in the ProcessNetwork */
+ protected Vector<Connection> _connectionList = null;
+}
--- /dev/null
+/* $Id: ProfilingConfiguration.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.datamodel.pn;\r
+\r
+import dol.visitor.PNVisitor;\r
+\r
+public class ProfilingConfiguration extends Configuration {\r
+\r
+ /**\r
+ * Constructor to create a ProfilerConfiguration.\r
+ */\r
+ public ProfilingConfiguration(String name) {\r
+ super(name);\r
+ }\r
+\r
+ /**\r
+ * Accept a Visitor.\r
+ *\r
+ * @param x visitor object\r
+ */\r
+ public void accept(PNVisitor x) {\r
+ x.visitComponent(this);\r
+ }\r
+\r
+ /**\r
+ * Clone this Configuration.\r
+ *\r
+ * @return new instance of the Configuration.\r
+ */\r
+ public Object clone() {\r
+ ProfilingConfiguration newObj = (ProfilingConfiguration) super.clone();\r
+ return newObj;\r
+ }\r
+\r
+}\r
--- /dev/null
+/* $Id: Resource.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import java.util.Vector;
+
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is the basic class which abstracts a resource of a generic
+ * process network. The resource has a name and a list of ports.
+ */
+public class Resource {
+
+ /**
+ * Constructor to create a resource with a name and an empty
+ * portList.
+ */
+ public Resource(String name) {
+ _name = name;
+ _basename = name;
+ _portList = new Vector<Port>();
+ _srcList = new Vector<SourceCode>();
+ _cfgList = new Vector<Configuration>();
+ _profilingList = new Vector<ProfilingConfiguration>();
+ }
+
+ /**
+ * Accept a Visitor
+ *
+ * @param x visitor object
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this resource.
+ *
+ * @return new instance of the resource.
+ */
+ @SuppressWarnings("unchecked")
+ public Object clone() {
+ try {
+ Resource newObj = (Resource) super.clone();
+ newObj.setName(_name);
+ newObj.setType(_type);
+ newObj.setBasename(_basename);
+ newObj.setPortList((Vector)_portList.clone() );
+ newObj.setSrcList((Vector)_srcList.clone() );
+ newObj.setCfgList((Vector)_cfgList.clone() );
+ newObj.setProfilingList((Vector)_profilingList.clone() );
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ public String getBasename() {
+ return _basename;
+ }
+
+ public void setBasename(String basename) {
+ _basename = basename;
+ }
+
+ /**
+ * Get the name of this resource.
+ *
+ * @return name of the resource
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this resource.
+ *
+ * @param name name of the resource
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the type of this resource.
+ *
+ * @return type of the resource
+ */
+ public String getType() {
+ return _type;
+ }
+
+ /**
+ * Set the type of this resource.
+ *
+ * @param type type of the resource
+ */
+ public void setType(String type) {
+ _type = type;
+ }
+
+ /**
+ * Get the list of source codes of this resource.
+ *
+ * @return list of source codes
+ */
+ public Vector<SourceCode> getSrcList() {
+ return _srcList;
+ }
+
+ /**
+ * Get the list of ports of this resource.
+ *
+ * @return list of ports
+ */
+ public Vector<Port> getPortList() {
+ return _portList;
+ }
+
+ /**
+ * Set the list of ports of this resource.
+ *
+ * @param portList port list
+ */
+ public void setPortList(Vector<Port> portList) {
+ _portList = portList;
+ }
+
+ /**
+ * Get the list of configurations of this resource.
+ *
+ * @return list of configurations
+ */
+ public Vector<Configuration> getCfgList() {
+ return _cfgList;
+ }
+
+ /**
+ * Set the list of configurations of this resource.
+ *
+ * @param cfgList configuration list
+ */
+ public void setCfgList(Vector<Configuration> cfgList) {
+ _cfgList = cfgList;
+ }
+
+ /**
+ * Get the list of profiling info of this resource.
+ *
+ * @return list of profiling info
+ */
+ public Vector<ProfilingConfiguration> getProfilingList() {
+ return _profilingList;
+ }
+
+ /**
+ * Set the list of profiling info of this resource.
+ *
+ * @param cfgList profiling info list
+ */
+ public void setProfilingList(Vector<ProfilingConfiguration> cfgList) {
+ _profilingList = cfgList;
+ }
+
+ /**
+ * Return a profiling which has a specific name. Return null when it
+ * cannot be found.
+ *
+ * @param name name of the profiling to search for
+ * @return profiling with the specified name
+ */
+ public ProfilingConfiguration getProfilingCfg(String name) {
+ for (ProfilingConfiguration cfg : _profilingList) {
+ if (cfg.getName().equals(name)) {
+ return cfg;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Set the list of source code of this resource.
+ *
+ * @param srcList port list
+ */
+ public void setSrcList(Vector<SourceCode> srcList) {
+ _srcList = srcList;
+ }
+
+ /**
+ * Get the hierarchical parent of this resource.
+ *
+ * @return parent of this resource
+ */
+ public Resource getParentResource() {
+ return _parentResource;
+ }
+
+ /**
+ * Set the hierarchical parent of this resource.
+ *
+ * @param parentResource new parent
+ */
+ public void setParentResource(Resource parentResource) {
+ _parentResource = parentResource;
+ }
+
+ /**
+ * Return a string representation of the resource.
+ *
+ * @return string representation of the resource
+ */
+ public String toString() {
+ return "Resource: " + _name;
+ }
+
+ /**
+ * Return a port which has a specific name. Return null when port
+ * cannot be found.
+ *
+ * @param name name of the port to search for
+ * @return port with the specified name
+ */
+ public Port getPort(String name) {
+ for (Port port : _portList) {
+ if (port.getName().equals(name)) {
+ return port;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return a port which has a specific name. Return null when port
+ * cannot be found.
+ *
+ * @return port with the specified name
+ */
+ public Port getFirstPort() {
+ return (Port) _portList.firstElement();
+ }
+
+ /** name of the resource */
+ protected String _name = null;
+
+ /** type of the resource */
+ protected String _type = null;
+
+ /** basename of the resource, if no basename, store the name */
+ protected String _basename = null;
+
+ /** list of the ports of the Resource */
+ protected Vector<Port> _portList = null;
+
+ /** list of the source codes of the Resource */
+ protected Vector<SourceCode> _srcList = null;
+
+ /** list of the configurations of the Resource */
+ protected Vector<Configuration> _cfgList = null;
+
+ /** list of the profiling info of the Resource */
+ protected Vector<ProfilingConfiguration> _profilingList = null;
+
+ /**
+ * parent resource of this resource in a hierarchical process network
+ */
+ protected Resource _parentResource = null;
+}
--- /dev/null
+/* $Id: Schedulable.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.datamodel.pn;\r
+\r
+/**\r
+ * Marker interface for all entities that can be added\r
+ * to a scheduler table.\r
+ */\r
+public interface Schedulable {\r
+\r
+}\r
--- /dev/null
+/* $Id: SourceCode.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is the basic source code of a process.
+ */
+public class SourceCode {
+
+ /**
+ * Constructor to create a SourceCode with a name.
+ */
+ public SourceCode(String name) {
+ _name = name;
+ }
+
+ /**
+ * Accept a visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this SourceCode.
+ *
+ * @return new instance of the SourceCode.
+ */
+ public Object clone() {
+ try {
+ SourceCode newObj = (SourceCode) super.clone();
+ newObj.setName(_name);
+ newObj.setType(_type);
+ newObj.setLocality(_locality);
+ newObj.setProcess( (Process) _process.clone() );
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the name of this SourceCode.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this SourceCode.
+ *
+ * @param name name of the SourceCode
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the process of this SourceCode.
+ *
+ * @return process to which this SourceCode belongs
+ */
+ public Process getProcess() {
+ return _process;
+ }
+
+ /**
+ * Set the proces of this SourceCode.
+ *
+ * @param process process to which this SourceCode belongs
+ */
+ public void setProcess(Process process) {
+ _process = process;
+ }
+
+ /**
+ * Get the locality of this SourceCode.
+ *
+ * @return locality of the SourceCode
+ */
+ public String getLocality() {
+ return _locality;
+ }
+
+ /**
+ * Set the locality of this SourceCode.
+ *
+ * @param locality locality of the SourceCode
+ */
+ public void setLocality(String locality) {
+ _locality = locality;
+ }
+
+ /**
+ * Get the type of this SourceCode.
+ *
+ * @return type of the SourceCode
+ */
+ public String getType() {
+ return _type;
+ }
+
+ /**
+ * Set the type of this SourceCode.
+ *
+ * @param type The new type
+ */
+ public void setType(String type) {
+ _type = type;
+ }
+
+ /**
+ * Return a string representation of the SourceCode.
+ *
+ * @return string representation of the SourceCode
+ */
+ public String toString() {
+ return "SourceCode: " + _name;
+ }
+
+ protected String _name = null;
+ protected Process _process = null;
+ protected String _type = null;
+ protected String _locality = null;
+}
--- /dev/null
+/* $Id: Variable.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.datamodel.pn;
+
+import dol.visitor.PNVisitor;
+
+/**
+ * This class represents a global variable in XML.
+ */
+public class Variable {
+
+ /**
+ * Constructor to create a Variable.
+ */
+ public Variable(String name) {
+ _name = name;
+ }
+
+ /**
+ * Accept a Visitor.
+ *
+ * @param x visitor object
+ */
+ public void accept(PNVisitor x) {
+ x.visitComponent(this);
+ }
+
+ /**
+ * Clone this Variable.
+ *
+ * @return new instance of the Variable.
+ */
+ public Object clone() {
+ try {
+ Variable newObj = (Variable) super.clone();
+ newObj.setName(_name);
+ return (newObj);
+ } catch (CloneNotSupportedException e) {
+ System.out.println("Error Clone not Supported");
+ }
+ return null;
+ }
+
+ /**
+ * Get the value of the Variable.
+ *
+ * @return the value of the variable
+ */
+ public int getValue() {
+ return _value;
+ }
+
+ /**
+ * Set the value of the Variable.
+ *
+ * @param value the value of the variable
+ */
+ public void setValue(int value) {
+ _value = value;
+ }
+
+ /**
+ * Get the name of this SourceCode.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Set the name of this SourceCode.
+ *
+ * @param name name of the SourceCode
+ */
+ public void setName(String name) {
+ _name = name;
+ }
+
+ /**
+ * Get the hierarchical parent of this resource.
+ *
+ * @return parent of this resource
+ */
+ public Resource getParentResource() {
+ return _parentResource;
+ }
+
+ /**
+ * Set the hierarchical parent of this resource.
+ *
+ * @param parentResource new parent
+ */
+ public void setParentResource(Resource parentResource) {
+ _parentResource = parentResource;
+ }
+
+ /**
+ * Return a string representation of the Variable.
+ *
+ * @return string representation of the Variable
+ */
+ public String toString() {
+ return "Variable: " + getName();
+ }
+
+ protected int _value;
+ protected String _name = null;
+ protected Resource _parentResource = null;
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Internal data model for the process network representation.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: ArchFlattener.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.flattener;
+
+import java.util.List;
+
+import org.jdom.Element;
+import org.jdom.Namespace;
+
+/**
+ *
+ */
+public class ArchFlattener extends FlattenerHelper {
+
+ /**
+ * Constructor.
+ *
+ * @param classname class name of the generated class
+ */
+ public ArchFlattener(String classname) {
+ super(classname);
+ }
+
+ public String processElement(Element element)
+ throws RuntimeException {
+
+ String string = "";
+
+ if (element.getName().equalsIgnoreCase("processor")) {
+ _generateElement = true;
+ string = generateProcessor(element);
+ }
+ else if (element.getName().equalsIgnoreCase("hw_channel")) {
+ _generateElement = true;
+ string = generateLink(element);
+ }
+ else if (element.getName().equalsIgnoreCase("memory")) {
+ _generateElement = true;
+ string = generateMemory(element);
+ }
+ else if (element.getName().equalsIgnoreCase("node")) {
+ _generateElement = true;
+ string = generateNode(element);
+ }
+
+ if (element.getName().equalsIgnoreCase("connection")) {
+ _generateElement = false;
+ string = generateConnection(element);
+ }
+
+ //belongs to mapping!
+ if (element.getName().equalsIgnoreCase("binding")) {
+ string = generateBinding(element);
+ }
+ return string;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateProcessor(Element element) {
+ String attributes[] = {"name", "type", "basename"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("iterator")) {
+ sourceCode += generateIterator(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("node")) {
+ sourceCode += generateNode(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("configuration")) {
+ sourceCode += generateConfiguration(childElement);
+ }
+
+ }
+ sourceCode += _indent + "System.out.println(\"</processor>\");\n";
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateMemory(Element element) {
+ String attributes[] = {"name", "type", "basename"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("iterator")) {
+ sourceCode += generateIterator(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("node")) {
+ sourceCode += generateNode(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("configuration")) {
+ sourceCode += generateConfiguration(childElement);
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</memory>\");\n";
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateLink(Element element) {
+ String attributes[] = {"name", "type", "basename"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("iterator")) {
+ sourceCode += generateIterator(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("node")) {
+ sourceCode += generateNode(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("configuration")) {
+ sourceCode += generateConfiguration(childElement);
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</hw_channel>\");\n";
+ return sourceCode;
+ }
+
+ protected String generateConfiguration(Element element) {
+ String attributes[] = {"name", "value"};
+ increaseXmlIndent();
+ String sourceCode = generateElement(element, attributes, true);
+ decreaseXmlIndent();
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateNode(Element element) {
+ increaseXmlIndent();
+
+ String sourceCode = "";
+ if (_generateElement) {
+ String attributes[] = {"name", "basename"};
+ sourceCode = generateElement(element, attributes, false);
+ }
+ else {
+ String attributes[] = {"name"};
+ sourceCode = generateElement(element, attributes, false);
+ }
+
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("duplexport")) {
+ sourceCode += generatePort(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("inputport")) {
+ sourceCode += generatePort(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("outputport")) {
+ sourceCode += generatePort(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("port")) {
+ sourceCode += generatePort(childElement);
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"" + _xmlIndent
+ + "</node>\");\n";
+
+ decreaseXmlIndent();
+ return sourceCode;
+ }
+
+ protected String generatePort(Element element) {
+ increaseXmlIndent();
+ String sourceCode = "";
+ if (_generateElement) {
+ String attributes[] = {"name", "basename"};
+ sourceCode = generateElement(element, attributes, true);
+ }
+ else {
+ String attributes[] = {"name"};
+ sourceCode = generateElement(element, attributes, true);
+ }
+ decreaseXmlIndent();
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateConnection(Element element) {
+ String attributes[] = {"name"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ //add origin and target elements
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("origin")) {
+ //origin found
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement, attributes, false);
+
+ Namespace ns= childElement.getNamespace();
+ Element nodeElement = childElement.getChild("node", ns);
+ if (nodeElement != null) {
+ sourceCode += generateNode(nodeElement);
+ }
+ sourceCode += _indent +
+ "System.out.println(\"" + _xmlIndent + "</origin>\");\n";
+ decreaseXmlIndent();
+ }
+ else if (childElement.getName().equalsIgnoreCase("target")) {
+ //target found
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement, attributes, false);
+
+ Namespace ns= childElement.getNamespace();
+ Element nodeElement = childElement.getChild("node", ns);
+ if (nodeElement != null) {
+ sourceCode += generateNode(nodeElement);
+ }
+ sourceCode += _indent +
+ "System.out.println(\"" + _xmlIndent + "</target>\");\n";
+ decreaseXmlIndent();
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</connection>\");\n";
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateBinding(Element element) {
+ String attributes[] = {"name", "parameter", "type"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ //add origin and target elements
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("origin")) {
+ //origin found
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement, attributes, false);
+
+ Namespace ns = childElement.getNamespace();
+ Element portElement = childElement.getChild("port", ns);
+ if (portElement != null) {
+ increaseXmlIndent();
+ String[] portAttributes = {"name", "basename"};
+ sourceCode += generateElement(portElement,
+ portAttributes, true);
+ decreaseXmlIndent();
+ }
+ sourceCode += _indent +
+ "System.out.println(\"" + _xmlIndent + "</origin>\");\n";
+ decreaseXmlIndent();
+ }
+ else if (childElement.getName().equalsIgnoreCase("target")) {
+ //target found
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement, attributes, false);
+
+ Namespace ns = childElement.getNamespace();
+ Element portElement = childElement.getChild("port", ns);
+ if (portElement != null) {
+ increaseXmlIndent();
+ String[] portAttributes = {"name", "basename"};
+ sourceCode += generateElement(portElement,
+ portAttributes, true);
+ decreaseXmlIndent();
+ }
+ sourceCode += _indent +
+ "System.out.println(\"" + _xmlIndent + "</target>\");\n";
+ decreaseXmlIndent();
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</binding>\");\n";
+ return sourceCode;
+ }
+}
--- /dev/null
+/* $Id: BugCatcher.java 1 2010-02-24 13:03:05Z haidw $ */
+
+package dol.helper.flattener;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXParseException;
+
+/**
+ *
+ */
+class BugCatcher implements ErrorHandler {
+ public void error(SAXParseException ex) {
+ System.out.println("[ERROR ]: "+ex.getMessage());
+
+ }
+
+ public void fatalError(SAXParseException ex) {
+ System.out.println("[PIZDEC ]: "+ex.getMessage());
+
+ }
+
+ public void warning(SAXParseException ex) {
+ System.out.println("[WARNING]: "+ex.getMessage());
+
+ }
+}
--- /dev/null
+/* $Id: DomDocumentParser.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.flattener;\r
+\r
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.apache.xerces.parsers.DOMParser;
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+\r
+/**\r
+ *\r
+ */\r
+public class DomDocumentParser {\r
+\r
+ DOMParser dp = null;\r
+ public ErrorHandler bc = new BugCatcher();\r
+\r
+ public DomDocumentParser() {\r
+ dp = new DOMParser();\r
+ dp.setErrorHandler(bc);\r
+ }\r
+\r
+ public Document parseDocument(File file){\r
+ try {\r
+ InputStream is = new FileInputStream(file);\r
+ InputSource iss = new InputSource(is);\r
+ dp.parse(iss);\r
+ return dp.getDocument();\r
+ } catch (Exception ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public Document parseDocument(String pathToFile){\r
+ return parseDocument(new File(pathToFile));\r
+ }\r
+}\r
--- /dev/null
+/* $Id: FlattenerHelper.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.flattener;
+
+import java.util.List;
+
+import org.jdom.Document;
+import org.jdom.Element;
+
+import dol.datamodel.XmlTag;
+
+/**
+ * Helper class to generate the source code of a class for writing
+ * an XML file based on an XML file with iterators. For details, refer
+ * to removeIterators().
+ *
+ * @see #removeIterators(org.jdom.Document doc)
+ */
+public class FlattenerHelper {
+
+ protected String _preamble = "public class Generator {\n\n public "
+ + "Generator() {\n //nothing to be done here\n }\n"
+ + "\n public static void main(String[] args) {\n";
+
+
+ //true, when an element is generated. places a restriction on the append
+ //element, namely that it must be a single variable, no function of a
+ //variable
+ protected boolean _generateElement = false;
+
+ protected String _indent = ""; //indentation of lines in Generator class
+
+ //code for obtaining range of iterator variables. is updated in each
+ //call of generateAppend
+ protected String _iteratorRangeCode = "";
+
+ //indentation of XML elements (use increaseXmlIndent() and
+ //decreaseXmlIndent() to change the indentation)
+ protected String _xmlIndent = "";
+
+ /**
+ * Default constructor. The generated class will have the name
+ * "Generator".
+ */
+ public FlattenerHelper() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param classname class name of the generated class
+ */
+ public FlattenerHelper(String classname) {
+ _preamble = _preamble.replace("Generator", classname);
+ }
+
+ public String processElement(Element element) {
+ return "";
+ }
+
+ /**
+ * Generate source code for println statement that prints out an XML
+ * element.
+ * @param element the XML element itself
+ * @param attributes attributes to include in the XML element
+ * @param standalone true, when element shall be closed. false, otherwise
+ * @return println statement which prints out the XML element
+ */
+ protected String generateElement(Element element,
+ String[] attributes, boolean standalone)
+ {
+ String sourceCode = _indent + "System.out.println(\"";
+ sourceCode += _xmlIndent + "<" + element.getName();
+ for (int i = 0; i < attributes.length; i++) {
+
+ if (attributes[i].equals("basename")) {
+ sourceCode += " " + attributes[i] + "=\\\"";
+ sourceCode += element.getAttributeValue("name");
+
+ if (!generateAppend(element).equals("")) {
+ sourceCode += "\\\"";
+ sourceCode += " range=\\\"" + _iteratorRangeCode;
+ }
+ sourceCode += "\\\"";
+ } else if (attributes[i].equals("name")) {
+ sourceCode += " " + attributes[i] + "=\\\"";
+ sourceCode += element.getAttributeValue("name");
+ sourceCode += generateAppend(element);
+ sourceCode += "\\\"";
+ } else if (attributes[i].equals("size")
+ && element.getName().equals(_xt.getSWChannelTag())) {
+ sourceCode += " " + attributes[i] + "=\\\"";
+ sourceCode += "\" + ";
+ sourceCode += element.getAttributeValue("size");
+ sourceCode += "+ \"";
+ sourceCode += "\\\"";
+ } else if (attributes[i].equals("tokensize")
+ && element.getName().equals(_xt.getSWChannelTag())) {
+ if (element.getAttributeValue("tokensize") != null) {
+ sourceCode += " " + attributes[i] + "=\\\"";
+ sourceCode += "\"";
+ sourceCode += " + ";
+ sourceCode += element.getAttributeValue("tokensize");
+ sourceCode += "+ \"";
+ sourceCode += "\\\"";
+ }
+ } else {
+ sourceCode += " " + attributes[i] + "=\\\"";
+ sourceCode += element.getAttributeValue(attributes[i]);
+ sourceCode += "\\\"";
+ }
+
+ }
+
+ if (standalone)
+ sourceCode += "/";
+ sourceCode +=">\");\n";
+
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ public String removeIterators(Document doc)
+ throws RuntimeException {
+ String sourceCode = _preamble;
+ String functionString = "";
+ String rootName = "";
+ _indent = " ";
+
+ Element root = doc.getRootElement();
+ String xmlns = root.getNamespaceURI();
+ String xsiLocation = "";
+ for (org.jdom.Attribute attr :
+ (List<org.jdom.Attribute>)root.getAttributes()) {
+ //System.out.println(attr.getName() + ": ");
+ //System.out.println(attr.getValue());
+ if (attr.getName().equals("schemaLocation"))
+ xsiLocation = attr.getValue();
+ }
+
+ if (!root.getChildren().isEmpty()) {
+ //if there are any elements in the document, create a new header
+ //for the xml document
+ rootName = root.getName();
+
+ sourceCode += _indent
+ + "java.util.Hashtable<String, Integer> table = "
+ + "new java.util.Hashtable<String, Integer>();\n";
+
+ sourceCode += _indent + "System.out.println(\""
+ + "<?xml version=\\\"1.0\\\" "
+ + "encoding=\\\"UTF-8\\\"?>\");\n";
+ sourceCode += _indent + "System.out.println(\"<"
+ + rootName + " xmlns=\\\"" + xmlns
+ + "\\\" xmlns:xsi=\\\"http://www.w3.org/2001/"
+ + "XMLSchema-instance\\\" \\n xsi:schemaLocation=\\\""
+ + xsiLocation + "\\\" name=\\\""
+ + root.getAttributeValue("name") + "_flattened"
+ + "\\\">\\n \");\n";
+ }
+
+
+ for (Element elmt : (List<Element>)root.getChildren()) {
+ try {
+ if (elmt.getName().equalsIgnoreCase(_xt.getIteratorTag())) {
+ sourceCode += generateIterator(elmt);
+ }
+ else if (elmt.getName().equalsIgnoreCase(_xt.getVariableTag())) {
+ sourceCode += generateVariable(elmt);
+ }
+ else if (elmt.getName().equalsIgnoreCase(_xt.getFunctionTag())) {
+ functionString += generateFunction(elmt);
+ }
+ else {
+ sourceCode += processElement(elmt);
+ }
+ }
+ catch (RuntimeException e) {
+ String elementName = "";
+ System.out.println(e.getMessage());
+ if (!elmt.getName().equalsIgnoreCase(_xt.getIteratorTag()) &&
+ !elmt.getName().equalsIgnoreCase(_xt.getVariableTag())) {
+ elementName = elmt.getAttributeValue("name");
+ }
+ throw new RuntimeException(
+ "Error: An error occurred while parsing the <"
+ + elmt.getName() + "> element \""
+ + elementName + "\".");
+ }
+ }
+
+ sourceCode += _indent + "System.out.println(\"</"
+ + rootName +">\");\n }\n";
+ _indent = " ";
+ sourceCode += functionString;
+ sourceCode += "\n}";
+
+ return sourceCode;
+ }
+
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateIterator(Element element) {
+ String variableName = element.getAttributeValue("variable");
+ /*
+ //extract the upper iteration boundary and construct the for loop
+ String forLoop = element.getAttributeValue("range");
+ String boundary = forLoop.replaceAll(
+ "for.*;[ ]*\\w*[ ]*[<>=]* *(.*);.*", "$1");
+ */
+ String forLoop = "for (int " + variableName + " = 0; " + variableName
+ + " < " + element.getAttributeValue("range") + "; "
+ + variableName + "++)";
+
+ String sourceCode = _indent + "table.put(\"" + variableName
+ + "\", " + element.getAttributeValue("range") + ");\n";
+
+ sourceCode += _indent + forLoop + " {\n";
+ _indent += " ";
+
+ for (Element el : (List<Element>)element.getChildren()) {
+ try {
+ if (el.getName().equalsIgnoreCase(_xt.getIteratorTag())) {
+ sourceCode += generateIterator(el);
+ }
+ else {
+ sourceCode += processElement(el);
+ }
+ }
+ catch (RuntimeException e) {
+ System.out.println(e.getMessage());
+ throw new RuntimeException(
+ "Error: An error occurred while parsing the <"
+ + el.getName() + "> element \""
+ + el.getAttributeValue("name") + "\".");
+ }
+ }
+ _indent = _indent.substring(0, _indent.length() - 2);
+ sourceCode += _indent + "}\n";
+ sourceCode += _indent + "table.remove(\"" + variableName + "\");\n";
+
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateAppend(Element element)
+ throws RuntimeException {
+ String sourceCode = "";
+
+ _iteratorRangeCode = "";
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("append")) {
+ if (_generateElement &&
+ !childElement.getAttributeValue(_xt.getFunctionTag()).replaceAll(
+ "\\w", "").equals("")) {
+ throw new RuntimeException("Error: Found \""
+ + childElement.getAttributeValue("function")
+ + "\" in <append>. When constructing elements with an "
+ + "iterator using <append function=\"xxx\">, xxx must "
+ + "be a single variable. No mathematical operations "
+ + "are permitted.");
+ }
+ sourceCode += "\" + \"_\" + ("
+ + childElement.getAttributeValue(_xt.getFunctionTag())
+ + ") + \"";
+
+ if (!_iteratorRangeCode.equals(""))
+ _iteratorRangeCode += ";";
+
+ _iteratorRangeCode += "\" + table.get(\""
+ + childElement.getAttributeValue(_xt.getFunctionTag())
+ + "\") + \"";
+ }
+ }
+ return sourceCode;
+ }
+
+ protected String generateVariable(Element element) {
+ String sourceCode = _indent + "int ";
+ sourceCode += element.getAttributeValue("name");
+ sourceCode += " = ";
+ sourceCode += element.getAttributeValue("value");
+ sourceCode += ";\n";
+ return sourceCode;
+ }
+
+ protected String generateFunction(Element element) {
+ return element.getText();
+ }
+
+ /**
+ * Increase the XML indentation.
+ **/
+ protected void increaseXmlIndent() {
+ _xmlIndent += " ";
+ }
+
+ /**
+ * Decrease the XML indentation.
+ */
+ protected void decreaseXmlIndent() {
+ _xmlIndent = _xmlIndent.substring(0, _xmlIndent.length() - 2);
+ }
+
+ protected XmlTag _xt = XmlTag.getInstance();
+}
--- /dev/null
+/* $Id: MappingFlattener.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.flattener;
+
+import java.util.List;
+
+import org.jdom.Element;
+
+/**
+ *
+ */
+public class MappingFlattener extends FlattenerHelper {
+
+ /**
+ * Constructor.
+ *
+ * @param classname class name of the generated class
+ */
+ public MappingFlattener(String classname) {
+ super(classname);
+ }
+
+ public String processElement(Element element)
+ throws RuntimeException {
+
+ String string = "";
+
+ if (element.getName().equalsIgnoreCase("binding")) {
+ _generateElement = false;
+ string = generateBinding(element);
+ }
+ else if (element.getName().equalsIgnoreCase("path")) {
+ _generateElement = false;
+ string = generatePath(element);
+ }
+ else if (element.getName().equalsIgnoreCase("schedule")) {
+ _generateElement = false;
+ string = generateSchedule(element);
+ }
+
+ return string;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generatePath(Element element) {
+ String attributes[] = {"name"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ //add origin and target elements
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("origin")
+ || childElement.getName().equalsIgnoreCase("target")) {
+ sourceCode += generateOriginOrTarget(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("resource")) {
+ String rAttributes[] = {"name"};
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement,rAttributes, false);
+ sourceCode += _indent +
+ "System.out.println(\"" + _xmlIndent + "</resource>\");\n";
+ decreaseXmlIndent();
+ }
+ else if (childElement.getName().equalsIgnoreCase("buffer")) {
+ String bAttributes[] = {"name"};
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement,bAttributes, false);
+ sourceCode += _indent +
+ "System.out.println(\"" + _xmlIndent + "</buffer>\");\n";
+ decreaseXmlIndent();
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</path>\");\n";
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateSchedule(Element element) {
+ String attributes[] = {"name", "type"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ //add origin and target elements
+
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("origin")) {
+ sourceCode += generateOriginOrTarget(childElement);
+ }
+ else if (childElement.getName().equalsIgnoreCase("resource")) {
+ String rAttributes[] = {"name"};
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement,rAttributes, false);
+ sourceCode += _indent +
+ "System.out.println(\"" + _xmlIndent + "</resource>\");\n";
+ decreaseXmlIndent();
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</schedule>\");\n";
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateBinding(Element element) {
+ String attributes[] = {"name", "type"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ //add origin and target elements
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("origin")
+ || childElement.getName().equalsIgnoreCase("target")) {
+ sourceCode += generateOriginOrTarget(childElement);
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</binding>\");\n";
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateOriginOrTarget(Element element) {
+ String attributes[] = {"name"};
+ increaseXmlIndent();
+ String sourceCode = generateElement(element, attributes, false);
+
+ //add configuration elements
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase(_xt.getConfigurationTag())) {
+ sourceCode += generateConfiguration(childElement);
+ }
+ }
+
+ sourceCode += _indent + "System.out.println(\"" + _xmlIndent + "</"
+ + element.getName() + ">\");\n";
+ decreaseXmlIndent();
+
+ return sourceCode;
+ }
+
+ protected String generateConfiguration(Element element) {
+ String attributes[] = {"name", "value"};
+ increaseXmlIndent();
+ String sourceCode = generateElement(element, attributes, true);
+ decreaseXmlIndent();
+ return sourceCode;
+ }
+
+
+}
--- /dev/null
+/* $Id: PNFlattener.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.flattener;
+
+import java.util.List;
+
+import org.jdom.Element;
+import org.jdom.Namespace;
+
+/**
+ *
+ */
+public class PNFlattener extends FlattenerHelper {
+
+ /**
+ * Constructor.
+ *
+ * @param classname class name of the generated class
+ */
+ public PNFlattener(String classname) {
+ super(classname);
+ }
+
+ public String processElement(Element element)
+ throws RuntimeException {
+
+ String string = "";
+
+ _generateElement = true;
+ if (element.getName().equalsIgnoreCase(_xt.getProcessTag())) {
+ string = generateProcess(element);
+ } else if (element.getName().equalsIgnoreCase(_xt.getSWChannelTag())) {
+ string = generateChannel(element);
+ } else if (element.getName().equalsIgnoreCase(_xt.getPortTag())) {
+ string = generatePort(element);
+ } else if (element.getName().equalsIgnoreCase(_xt.getConfigurationTag())) {
+ string = generateConfiguration(element);
+ } else if (element.getName().equalsIgnoreCase(_xt.getProfilingTag())) {
+ string = generateProfiling(element);
+ }
+
+ _generateElement = false;
+
+ if (element.getName().equalsIgnoreCase(_xt.getConnectionTag())) {
+ string = generateConnection(element);
+ }
+ return string;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateProcess(Element element) {
+ String attributes[] = {"name", "basename"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (!(childElement.getName().equalsIgnoreCase(_xt.getPortTag()) ||
+ childElement.getName().equalsIgnoreCase(_xt.getSourceTag()) ||
+ childElement.getName().equalsIgnoreCase(_xt.getConfigurationTag()) ||
+ childElement.getName().equalsIgnoreCase(_xt.getProfilingTag()))) {
+ if (childElement.getName().equalsIgnoreCase(_xt.getIteratorTag())) {
+ sourceCode += generateIterator(childElement);
+ }
+ } else {
+ if (childElement.getName().equalsIgnoreCase(_xt.getPortTag())) {
+ sourceCode += generatePort(childElement);
+ } else if (childElement.getName().equalsIgnoreCase(_xt.getConfigurationTag())) {
+ sourceCode += generateConfiguration(childElement);
+ } else if (childElement.getName().equalsIgnoreCase(_xt.getProfilingTag())) {
+ sourceCode += generateProfiling(childElement);
+ }
+ else {
+ //source found
+ increaseXmlIndent();
+ String[] sourceAttributes = {"location", "type"};
+ sourceCode += generateElement(childElement,
+ sourceAttributes, true);
+ decreaseXmlIndent();
+ }
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</process>\");\n";
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateChannel(Element element) {
+ String attributes[] = {"name", "type", "size",
+ "basename", "tokensize"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase(_xt.getPortTag())) {
+ sourceCode += generatePort(childElement);
+ } else if (childElement.getName().equalsIgnoreCase(_xt.getConfigurationTag())) {
+ sourceCode += generateConfiguration(childElement);
+ } else if (childElement.getName().equalsIgnoreCase(_xt.getProfilingTag())) {
+ sourceCode += generateProfiling(childElement);
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</sw_channel>\");\n";
+ return sourceCode;
+ }
+
+ protected String generatePort(Element element) {
+ String attributes[] = {"name", "type", "basename"};
+ increaseXmlIndent();
+ String sourceCode = generateElement(element, attributes, true);
+ decreaseXmlIndent();
+ return sourceCode;
+ }
+
+ protected String generateConfiguration(Element element) {
+ String attributes[] = {"name", "value"};
+ increaseXmlIndent();
+ String sourceCode = generateElement(element, attributes, true);
+ decreaseXmlIndent();
+ return sourceCode;
+ }
+
+ protected String generateProfiling(Element element) {
+ String attributes[] = {"name", "value"};
+ increaseXmlIndent();
+ String sourceCode = generateElement(element, attributes, true);
+ decreaseXmlIndent();
+ return sourceCode;
+ }
+
+ /**
+ *
+ */
+ @SuppressWarnings("unchecked")
+ protected String generateConnection(Element element) {
+ String attributes[] = {"name"};
+ String sourceCode = generateElement(element, attributes, false);
+
+ //add origin and target elements
+ for (Element childElement : (List<Element>)element.getChildren()) {
+ if (childElement.getName().equalsIgnoreCase("origin")) {
+ //origin found
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement, attributes, false);
+
+ Namespace ns = childElement.getNamespace();
+ Element portElement = childElement.getChild("port", ns);
+ if (portElement != null) {
+ increaseXmlIndent();
+ String[] portAttributes = {"name"};
+ sourceCode += generateElement(portElement,
+ portAttributes, true);
+ decreaseXmlIndent();
+ }
+ decreaseXmlIndent();
+ sourceCode += _indent +
+ "System.out.println(\" </" + _xt.getOriginTag()+">\");\n";
+ }
+ else if (childElement.getName().equalsIgnoreCase(_xt.getTargetTag())) {
+ //target found
+ increaseXmlIndent();
+ sourceCode += generateElement(childElement, attributes, false);
+
+ Namespace ns = childElement.getNamespace();
+ Element portElement = childElement.getChild(_xt.getPortTag(), ns);
+ if (portElement != null) {
+ increaseXmlIndent();
+ String[] portAttributes = {"name"};
+ sourceCode += generateElement(portElement,
+ portAttributes, true);
+ decreaseXmlIndent();
+ }
+ decreaseXmlIndent();
+ sourceCode += _indent +
+ "System.out.println(\" </"+_xt.getTargetTag()+">\");\n";
+ }
+ }
+ sourceCode += _indent + "System.out.println(\"</"
+ + _xt.getConnectionTag() + ">\");\n";
+ return sourceCode;
+ }
+}
--- /dev/null
+/* $Id: SaxDocumentParser.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.flattener;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import org.apache.xerces.parsers.SAXParser;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ */
+class SaxDocumentParser implements ContentHandler{
+
+ public ErrorHandler bc = new BugCatcher();
+ public SAXParser sp = null;
+ protected boolean foundIterator = false;
+
+ public SaxDocumentParser() {
+ try {
+ sp = new SAXParser();
+ sp.setFeature("http://xml.org/sax/features/validation",true);
+ sp.setFeature("http://apache.org/xml/features/validation/schema", true);
+ sp.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
+ sp.setErrorHandler(bc);
+ sp.setContentHandler(this);
+ sp.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",
+ dol.util.SchemaLocation.getInternalSchemaLocation());
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public boolean parseDocument(String pathToFile){
+ return parseDocument(new File(pathToFile));
+ }
+
+ public boolean parseDocument(File file){
+ try{
+ InputStream is = new FileInputStream(file);
+ InputSource iss = new InputSource(is);
+ sp.parse(iss);
+ }
+ catch (Exception e){
+ e.printStackTrace();
+ }
+ return true;//foundIterator;
+ }
+
+ /**
+ * Action to be done while parsing a start element of an XML
+ *
+ * @param elementName Description of the Parameter
+ * @param attributes Description of the Parameter
+ * @exception SAXException MyException If such and such occurs
+ */
+ public void startElement(String namespaceURI, String localName, String elementName, Attributes attributes) throws SAXException {
+
+ if (elementName.equals("iterator")) {
+ //System.out.println();
+ //System.out.println("Iterator found in document");
+ foundIterator = true;
+ }
+ else {
+ System.out.print(".");
+ }
+ }
+
+
+ public void startDocument() throws SAXException {
+ }
+
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ }
+
+ public void endDocument() throws SAXException {
+ }
+
+ public void endElement(String namespaceURI, String localName, String elementName) throws SAXException {
+ }
+
+ public void endPrefixMapping(String prefix) throws SAXException {
+ }
+
+ public void characters(char buf[], int offset, int len) throws SAXException {
+ }
+
+ public void skippedEntity(String string){
+ }
+
+ public void processingInstruction(String string1, String string2){
+ }
+
+ public void ignorableWhitespace(char[] characters,int int1,int int2){
+ }
+
+ public void setDocumentLocator(org.xml.sax.Locator dl){
+ }
+
+ }
+
--- /dev/null
+/* $Id: XMLFlattener.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.flattener;
+
+import java.io.File;
+import java.io.FileWriter;
+
+import org.jdom.input.DOMBuilder;
+import org.w3c.dom.Document;
+
+/**
+ *
+ */
+public class XMLFlattener {
+
+ public static void main(String[] args) {
+
+ if (args.length != 2) {
+ System.out.println("Wrong number of arguments.");
+ System.out.println("Correct call:");
+ System.out.println("java XMLFlattener in.xml out.xml");
+ System.exit(-1);
+ }
+ else {
+ SaxDocumentParser sdp = new SaxDocumentParser();
+ boolean needsToBeFlattened = false;
+ needsToBeFlattened = sdp.parseDocument(args[0]);
+ if (needsToBeFlattened) {
+ // start also with DOM Parser and generate the XML-Generator
+ DomDocumentParser ddp = new DomDocumentParser();
+ Document doc = ddp.parseDocument(args[0]);
+
+ DOMBuilder db = new DOMBuilder();
+ org.jdom.Document document = db.build(doc);
+
+ String xmlns = document.getRootElement().getNamespaceURI();
+
+ String outString = "";
+
+ if (xmlns.endsWith("PROCESSNETWORK") ||
+ xmlns.endsWith("processnetwork")) {
+ PNFlattener flattener = new PNFlattener(args[1]);
+ outString = flattener.removeIterators(document);
+ }
+ else if (xmlns.endsWith("ARCHITECTURE")
+ || xmlns.endsWith("ARCHITECTURE_OLD")
+ || xmlns.endsWith("architecture")) {
+ ArchFlattener flattener = new ArchFlattener(args[1]);
+ outString = flattener.removeIterators(document);
+ }
+ else if (xmlns.endsWith("MAPPING")
+ || xmlns.endsWith("MAPPING_OLD")
+ || xmlns.endsWith("mapping")) {
+ MappingFlattener flattener = new MappingFlattener(args[1]);
+ outString = flattener.removeIterators(document);
+ }
+
+
+ try {
+ FileWriter fw = new FileWriter(new File(args[1] + ".java"));
+ fw.write(outString);
+ fw.flush();
+ fw.close();
+ } catch (Exception ex) {
+ }
+ }
+ else {
+ System.out.println("Nothing to be done. Terminating...");
+ }
+ }
+ }
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Flattener which unfolds all iterators inside XML files.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: ChannelProfile.java 203 2010-10-11 08:59:47Z dchokshi $ */\r
+package dol.helper.profiler;\r
+\r
+/**\r
+ * Functional simulation profile information for a channel.\r
+ */\r
+public class ChannelProfile {\r
+\r
+ /**\r
+ * Constructor.\r
+ *\r
+ * @param name name of the channel this profile belongs to\r
+ * @param capacity capacity of this channel\r
+ */\r
+ public ChannelProfile(String name, int capacity) {\r
+ _name = name;\r
+ _capacity = capacity;\r
+ }\r
+\r
+ /**\r
+ * Adds a read access. Reduces the fifo fill level accordingly. If the\r
+ * amount is larger than the current fifo size, the read is blocking.\r
+ * \r
+ * @param amount The amount of data in bytes.\r
+ */\r
+ public void readAccess(int amount) {\r
+ _numOfReads++;\r
+ _totalReadData += amount;\r
+\r
+ if (amount > _maxReadChunk)\r
+ _maxReadChunk = amount;\r
+\r
+ if (amount < _minReadChunk)\r
+ _minReadChunk = amount;\r
+\r
+ if (_fillLevel < amount) {\r
+ _numOfBlockingReads++;\r
+ _blockedReadSize = amount;\r
+ }\r
+ else {\r
+ _fillLevel -= amount;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Adds a write access. Enlarges the fifo size accordingly. If the\r
+ * amount plus the current size of the fifo is larger than the\r
+ * capacity, an overflow occurs (blocking write).\r
+ *\r
+ * @param amount The amount of data in bytes.\r
+ */\r
+ public void writeAccess(int amount) {\r
+ _numOfWrites++;\r
+ if (_fillLevel + amount > _capacity) {\r
+ _numOfBlockingWrites++;\r
+ }\r
+\r
+ _fillLevel += amount;\r
+\r
+ if (amount > _maxWriteChunk)\r
+ _maxWriteChunk = amount;\r
+\r
+ if (amount < _minWriteChunk)\r
+ _minWriteChunk = amount;\r
+\r
+ if (_fillLevel > _maxFillLevel)\r
+ _maxFillLevel = _fillLevel;\r
+\r
+\r
+ if ((_fillLevel >= _blockedReadSize) && (_blockedReadSize != 0)) {\r
+ _fillLevel -= _blockedReadSize;\r
+ _blockedReadSize = 0;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the maximum amount of data stored in the fifo.\r
+ * \r
+ * @return Maximum fill level in bytes.\r
+ */\r
+ public int getMaxFillLevel() {\r
+ return _maxFillLevel;\r
+ }\r
+\r
+ /**\r
+ * Returns the size of the largest chunk of data read in a single\r
+ * read access.\r
+ * \r
+ * @return Size of the largest read chunk in bytes.\r
+ */\r
+ public int getMaxReadChunk() {\r
+ return _maxReadChunk;\r
+ }\r
+\r
+ /**\r
+ * Returns the size of the smallest chunk of data read in a single\r
+ * read access.\r
+ * \r
+ * @return Size of the smallest read chunk in bytes.\r
+ */\r
+ public int getMinReadChunk() {\r
+ return _minReadChunk;\r
+ }\r
+\r
+ /**\r
+ * Returns the size of the largest chunk of data written in a single\r
+ * write access.\r
+ * \r
+ * @return Size of the largest written chunk in bytes.\r
+ */\r
+ public int getMaxWriteChunk() {\r
+ return _maxWriteChunk;\r
+ }\r
+\r
+ /**\r
+ * Returns the size of the smallest chunk of data written in a single\r
+ * write access.\r
+ * \r
+ * @return Size of the smallest written chunk in bytes.\r
+ */\r
+ public int getMinWriteChunk() {\r
+ return _minWriteChunk;\r
+ }\r
+\r
+ /**\r
+ * Returns the number of total read accesses.\r
+ * \r
+ * @return Number of total read accesses.\r
+ */\r
+ public int getNumOfReads() {\r
+ return _numOfReads;\r
+ }\r
+\r
+ /**\r
+ * Returns the number of total blocking reads.\r
+ * A blocking read occurs whenever there is an attempt to read more\r
+ * data from the fifo than the fifo contains.\r
+ * \r
+ * @return Number of total blocking reads\r
+ */\r
+ public int getNumOfBlockingReads() {\r
+ return _numOfBlockingReads;\r
+ }\r
+\r
+ /**\r
+ * Returns the total number of write accesses.\r
+ * \r
+ * @return Number of total write accesses.\r
+ */\r
+ public int getNumOfWrites() {\r
+ return _numOfWrites;\r
+ }\r
+\r
+ /**\r
+ * Returns the number of total blocking writes.\r
+ * A blocking write occurs, whenever a write access tries to write\r
+ * more data into the fifo than its capacity allows.\r
+ * \r
+ * @return Number of total overflows.\r
+ */\r
+ public int getNumOfOverflows() {\r
+ return _numOfBlockingWrites;\r
+ }\r
+\r
+ /**\r
+ * Returns the percentage of read accesses which were blocking.\r
+ * @return Percentage of blocking reads\r
+ */\r
+ public int getBlockingReadsPercentage() {\r
+ if (_numOfReads == 0)\r
+ return 0;\r
+ \r
+ return (_numOfBlockingReads * 100) / (_numOfReads);\r
+ }\r
+ /**\r
+ * Returns the percentage of write accesses, which led to an overflow.\r
+ * @return Percentage of overflows.\r
+ */\r
+ public int getBlockingWritesPercentage() {\r
+ if (_numOfWrites == 0)\r
+ return 0;\r
+ \r
+ return (_numOfBlockingWrites * 100) / (_numOfWrites);\r
+ }\r
+ \r
+ /**\r
+ * Returns the total amount of read data (in bytes).\r
+ * @return Amount in bytes.\r
+ */\r
+ public long getTotalReadData() {\r
+ return _totalReadData;\r
+ }\r
+\r
+ /**\r
+ * Return the name of the channel this profile belongs to.\r
+ * \r
+ * @return name of the channel this profile belongs to\r
+ */\r
+ public String getName() {\r
+ return _name;\r
+ }\r
+\r
+\r
+ protected String _name = "";\r
+ protected int _capacity = 0;\r
+\r
+ protected long _totalReadData = 0;\r
+ protected int _fillLevel = 0;\r
+ protected int _maxFillLevel = 0;\r
+\r
+ protected int _numOfReads = 0;\r
+ protected int _numOfBlockingReads = 0;\r
+ protected int _maxReadChunk = 0;\r
+ protected int _minReadChunk = Integer.MAX_VALUE;\r
+ protected int _blockedReadSize = 0;\r
+\r
+ protected int _numOfWrites = 0;\r
+ protected int _numOfBlockingWrites = 0;\r
+ protected int _maxWriteChunk = 0;\r
+ protected int _minWriteChunk = Integer.MAX_VALUE;\r
+}\r
--- /dev/null
+/* $Id: Constants.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.helper.profiler;\r
+\r
+/**\r
+ * Keys for accessing profile properties.\r
+ */\r
+public class Constants {\r
+ public final static String processFires = "Process.Fires";\r
+ public final static String portAccesses = "Port.Accesses";\r
+ public final static String portTokenSize = "Port.TokenSize";\r
+ public final static String portInitialAccesses = "Port.InitialAccesses";\r
+ public final static String portInitialTokenSize = "Port.IntialTokensize";\r
+}\r
--- /dev/null
+/* $Id: PNProfileSummarizer.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.helper.profiler;\r
+\r
+import java.util.HashMap;\r
+import java.util.StringTokenizer;\r
+\r
+import dol.datamodel.pn.Process;\r
+import dol.datamodel.pn.ProcessNetwork;\r
+import dol.datamodel.pn.ProfilingConfiguration;\r
+import dol.parser.xml.pnschema.PNXmlParser;\r
+import dol.visitor.xml.PNXmlVisitor;\r
+\r
+/**\r
+ * Class to post-process profiling info in a process network XML file.\r
+ */\r
+public class PNProfileSummarizer {\r
+ /**\r
+ * Add up all WCED, BCED, and ACED numbers for each process in the\r
+ * given process network file. The computed numbers are back-annotated\r
+ * to a new file with the suffix _summary.\r
+ *\r
+ * @param filename filename of annotated process network XML file\r
+ */\r
+ public static void sumDemands(String filename) {\r
+ HashMap<String, ProfilingConfiguration> configs =\r
+ new HashMap<String, ProfilingConfiguration>();\r
+\r
+ //load process network specification from XML\r
+ PNXmlParser parserPn = new PNXmlParser();\r
+ ProcessNetwork pn = parserPn.doParse(filename);\r
+\r
+ for (Process process : pn.getProcessList()) {\r
+ //System.out.println(process.getName());\r
+ for (ProfilingConfiguration cfg :\r
+ process.getProfilingList()) {\r
+ StringTokenizer tokenizer =\r
+ new StringTokenizer(cfg.getName(), " ");\r
+ //System.out.println(cfg.getName());\r
+ if (tokenizer.countTokens() < 2) {\r
+ continue;\r
+ }\r
+\r
+ String demandId = tokenizer.nextToken();\r
+ String processorName = tokenizer.nextToken();\r
+ String key = process.getName() + " " + demandId + " "\r
+ + processorName + " sum";\r
+ if (configs.get(key) == null) {\r
+ ProfilingConfiguration config =\r
+ new ProfilingConfiguration(demandId + " "\r
+ + processorName + " sum");\r
+ config.setValue("0");\r
+ configs.put(key, config);\r
+ }\r
+ ProfilingConfiguration currentCfg = configs.get(key);\r
+ /*\r
+ System.out.print(currentCfg.getName() + ": "\r
+ + currentCfg.getValue() + " / "\r
+ + cfg.getName() + ": "\r
+ + cfg.getValue());\r
+ */\r
+ currentCfg.setValue(\r
+ Long.toString(Long.parseLong(\r
+ currentCfg.getValue())\r
+ + Long.parseLong(cfg.getValue())));\r
+ /*\r
+ System.out.println(currentCfg.getName() + ": "\r
+ + currentCfg.getValue());\r
+ */\r
+ }\r
+ }\r
+\r
+ for(String key : configs.keySet()) {\r
+ ProfilingConfiguration value = configs.get(key);\r
+ String process = key.substring(0, key.indexOf(" "));\r
+ pn.getProcess(process).getProfilingList().add(value);\r
+ }\r
+\r
+ System.out.println("Write process network XML file");\r
+ StringBuffer buffer = new StringBuffer();\r
+ pn.accept(new PNXmlVisitor(buffer));\r
+ try {\r
+ java.io.BufferedWriter writer =\r
+ new java.io.BufferedWriter(\r
+ new java.io.FileWriter(\r
+ filename.replaceAll(".xml", "_summary.xml")));\r
+ writer.write(buffer.toString());\r
+ writer.close();\r
+ } catch (java.io.IOException e) {\r
+ System.out.println("Caught an exception while "\r
+ + "creating XML file: " + e.getMessage());\r
+ e.printStackTrace(System.out);\r
+ }\r
+ System.out.println(" -- Process network XML file [Finished]");\r
+ }\r
+\r
+\r
+ /**\r
+ * Run summarize operations on annotated process network.\r
+ *\r
+ * @param args filename of annotated process network XML file\r
+ */\r
+ public static void main(String args[]) throws Exception {\r
+ PNProfileSummarizer.sumDemands(args[0]);\r
+ }\r
+}\r
--- /dev/null
+/* $Id: PortProfile.java 203 2010-10-11 08:59:47Z dchokshi $ */\r
+package dol.helper.profiler;\r
+\r
+/**\r
+ * Functional simulation profile information for a port.\r
+ */\r
+public class PortProfile {\r
+\r
+ /**\r
+ * Constructor.\r
+ *\r
+ * @param name name of the port this profile belongs to\r
+ */\r
+ public PortProfile(String name, ProcessProfile processProfile) {\r
+ _name = name;\r
+ _processProfile = processProfile;\r
+ _accesses = new Range();\r
+ _tokenSize = new Range();\r
+ _currentTokenSize = new Range();\r
+ }\r
+\r
+ /**\r
+ * Return the name of the channel this profile belongs to.\r
+ *\r
+ * @return name of the channel this profile belongs to\r
+ */\r
+ public String getName() {\r
+ return _name;\r
+ }\r
+\r
+ /**\r
+ * Add a read or write access to this port.\r
+ *\r
+ * @param tokenSize number of bytes communicated in this access\r
+ */\r
+ public void addAccess(int tokenSize) {\r
+ _currentAccesses++;\r
+ _currentTokenSize.merge(tokenSize);\r
+ }\r
+\r
+ /**\r
+ * Add an initial read or write access to this port (access happened\r
+ * during init() phase).\r
+ *\r
+ * @param tokenSize number of bytes communicated in this access\r
+ */\r
+ public void addInitialAccess(int tokenSize) {\r
+ _initialAccesses++;\r
+ if (_initialTokenSize == null) {\r
+ _initialTokenSize = new Range(tokenSize);\r
+ } else {\r
+ _initialTokenSize.merge(tokenSize);\r
+ }\r
+ }\r
+\r
+ /**\r
+ *\r
+ */\r
+ public void update() {\r
+ _accesses.merge(_currentAccesses);\r
+ _tokenSize.merge(_currentTokenSize);\r
+\r
+ _currentAccesses = 0;\r
+ _currentTokenSize.reset();\r
+ }\r
+\r
+ public int getInitialAccesses() {\r
+ return _initialAccesses;\r
+ }\r
+\r
+ public Range getInitialTokenSize() {\r
+ if (_initialTokenSize == null) {\r
+ return new Range(0);\r
+ } else {\r
+ return _initialTokenSize;\r
+ }\r
+ }\r
+\r
+ public Range getAccesses() {\r
+ return _accesses;\r
+ }\r
+\r
+ public Range getTokenSize() {\r
+ return _tokenSize;\r
+ }\r
+\r
+ String _name;\r
+ Range _accesses;\r
+ Range _tokenSize;\r
+ int _currentAccesses;\r
+ Range _currentTokenSize;\r
+ int _initialAccesses;\r
+ Range _initialTokenSize = null;\r
+ ProcessProfile _processProfile;\r
+}\r
--- /dev/null
+/* $Id: ProcessProfile.java 203 2010-10-11 08:59:47Z dchokshi $ */\r
+package dol.helper.profiler;\r
+\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+\r
+/**\r
+ * Functional simulation profile information for a process.\r
+ */\r
+public class ProcessProfile {\r
+\r
+ /** \r
+ * Constructor.\r
+ * \r
+ * @param name name of the process this profile belongs to \r
+ */\r
+ public ProcessProfile(String name) {\r
+ _name = name;\r
+ _portProfiles = new HashMap<String, PortProfile>();\r
+ }\r
+\r
+ /**\r
+ * Indicate that the process has entered fire().\r
+ */\r
+ public void start() {\r
+ _started = true;\r
+ _numOfFires++;\r
+ }\r
+ \r
+ /**\r
+ * Indicate that the process has leaved fire().\r
+ */\r
+ public void stop() {\r
+ if (!_started) {\r
+ return;\r
+ }\r
+ \r
+ _started = false;\r
+\r
+ Iterator<String> iterator = _portProfiles.keySet().iterator();\r
+\r
+ while (iterator.hasNext()) {\r
+ PortProfile profile = _portProfiles.get(iterator.next());\r
+ profile.update();\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Indicate a read or write access to a port.\r
+ * \r
+ * @param port the accessed port\r
+ * @param amount number of bytes communicated\r
+ */\r
+ public void portAccess(String port, int amount) {\r
+ if (_portProfiles.get(port) == null) {\r
+ PortProfile profile = new PortProfile(port, this);\r
+ _portProfiles.put(port, profile);\r
+ }\r
+ if (_started) {\r
+ _portProfiles.get(port).addAccess(amount);\r
+ } else {\r
+ _portProfiles.get(port).addInitialAccess(amount);\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Return the number of firings.\r
+ *\r
+ * @return the number of fire() calls of a process.\r
+ **/\r
+ public int getNumOfFires() {\r
+ return _numOfFires;\r
+ }\r
+ \r
+ /**\r
+ * Return the name of the process this profile belongs to.\r
+ * \r
+ * @return name of the process this profile belongs to\r
+ */\r
+ public String getName() {\r
+ return _name;\r
+ }\r
+\r
+ /**\r
+ * Return the profiles of all ports.\r
+ * \r
+ * @return profile of all ports\r
+ */\r
+ public HashMap<String, PortProfile> getPortProfiles() {\r
+ return _portProfiles;\r
+ }\r
+ \r
+ protected String _name;\r
+ boolean _started = false;\r
+ protected int _numOfFires = 0;\r
+ HashMap<String, PortProfile> _portProfiles;\r
+}\r
--- /dev/null
+/* $Id: ProfileParser.java 203 2010-10-11 08:59:47Z dchokshi $ */\r
+package dol.helper.profiler;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.FileReader;\r
+import java.io.IOException;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.StringTokenizer;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * Class for parsing a profile and collecting parameter statistics.\r
+ */\r
+public class ProfileParser {\r
+\r
+ /**\r
+ * Constructor.\r
+ **/\r
+ public ProfileParser(String filename) {\r
+ try {\r
+ _in = new BufferedReader(new FileReader(filename));\r
+ } catch (IOException e) {\r
+ System.err.println(e.getLocalizedMessage());\r
+ }\r
+\r
+ _processProfiles = new HashMap<String, ProcessProfile>();\r
+ _channelProfiles = new HashMap<String, ChannelProfile>();\r
+ _inPortToChannelMapping = new HashMap<String, String>();\r
+ _outPortToChannelMapping = new HashMap<String, String>();\r
+ _processCommOrder = new HashMap<String, Vector<String>>();\r
+ }\r
+\r
+ /**\r
+ * Parse the profile file and generate the profiles for processes and\r
+ * channels. After calling this function, use\r
+ * {@link #getProcessProfiles()} and {@link #getChannelProfiles()} to\r
+ * obtain the result of parsing.\r
+ *\r
+ * @see #getChannelProfiles()\r
+ * @see #getProcessProfiles()\r
+ */\r
+ public void parseProfile() {\r
+ String nextWord;\r
+ String line = null;\r
+\r
+ while (true) {\r
+ try {\r
+ //PERFORMANCE: do not read line-by-line but read in larger\r
+ //chunks from the file. has much more influence on the\r
+ //performance than the data structures in this class.\r
+ line = _in.readLine();\r
+ if (line == null) {\r
+ _in.close();\r
+\r
+ Iterator<String> iterator = _processProfiles.keySet().iterator();\r
+ while (iterator.hasNext()) {\r
+ _processProfiles.get(iterator.next()).stop();\r
+ }\r
+ return;\r
+ }\r
+ } catch (IOException e) {\r
+ System.err.println(e.getLocalizedMessage());\r
+ return;\r
+ }\r
+\r
+ StringTokenizer tokenizer = new StringTokenizer(line);\r
+ nextWord = tokenizer.nextToken();\r
+\r
+ if (nextWord.equals("c")) {\r
+ //'c' stands for a channel connection line. example:\r
+ //c filterchannel 8 o filter 0x23c738 i filter 0x23c6e8\r
+ String channelName = tokenizer.nextToken();\r
+ int capacity = Integer.parseInt(\r
+ tokenizer.nextToken());\r
+ String portAType = tokenizer.nextToken();\r
+ String processAName = tokenizer.nextToken();\r
+ String portAName = tokenizer.nextToken();\r
+ String portBType = tokenizer.nextToken();\r
+ String processBName = tokenizer.nextToken();\r
+ String portBName = tokenizer.nextToken();\r
+ addChannelProfile(channelName, capacity,\r
+ portAType, processAName, portAName,\r
+ portBType, processBName, portBName);\r
+ } else {\r
+ //current line is an event. examples:\r
+ //examples:\r
+ //78 filter started.\r
+ //79 filter r 0x23c6c0 8\r
+ //80 filter w 0x23c738 8\r
+ //81 filter stopped.\r
+\r
+ int i = Integer.parseInt(nextWord);\r
+ if (i != _lineCounter) {\r
+ System.err.println("Input file corrupt: line number "\r
+ + "expected.");\r
+ return;\r
+ }\r
+\r
+ //get process name\r
+ String processName = tokenizer.nextToken();\r
+ if (_processProfiles.get(processName) == null) {\r
+ ProcessProfile processProfile = new ProcessProfile(\r
+ processName);\r
+ _processProfiles.put(processName, processProfile);\r
+ }\r
+ if(_processCommOrder.get(processName) == null) {\r
+ _processCommOrder.put(processName, new Vector<String>());\r
+ }\r
+\r
+ nextWord = tokenizer.nextToken();\r
+ if(nextWord.equals("started.")) {\r
+ _processProfiles.get(processName).start();\r
+ }\r
+ else if(nextWord.equals("stopped.")) {\r
+ _processProfiles.get(processName).stop();\r
+ }\r
+ else if (nextWord.equals("r") || nextWord.equals("w")) {\r
+ String accessType = nextWord;\r
+ String portName = tokenizer.nextToken();\r
+ int amount = Integer.parseInt(\r
+ tokenizer.nextToken());\r
+ try {\r
+ _processProfiles.get(processName).\r
+ portAccess(portName, amount);\r
+ if (accessType.equals("r")) {\r
+ String channelName =\r
+ _inPortToChannelMapping.get(portName);\r
+ _channelProfiles.get(channelName).\r
+ readAccess(amount);\r
+ _processCommOrder.get(processName).add(channelName);\r
+\r
+ } else {\r
+ String channelName =\r
+ _outPortToChannelMapping.get(portName);\r
+ _channelProfiles.get(channelName).\r
+ writeAccess(amount);\r
+ _processCommOrder.get(processName).add(channelName);\r
+ }\r
+ } catch (NullPointerException e) {\r
+ System.err.println("Input file corrupt: cannot "\r
+ + "find channel associated to port "\r
+ + portName + "(line "\r
+ + _lineCounter + ").");\r
+ e.printStackTrace();\r
+ return;\r
+ }\r
+ } else {\r
+ System.err.println("Input file corrupt: unknown "\r
+ + "event type (line " + _lineCounter + ").");\r
+ return;\r
+ }\r
+ _lineCounter++;\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Return the profiles of all processes.\r
+ *\r
+ * @return profile of all processes\r
+ */\r
+ public HashMap<String, ProcessProfile> getProcessProfiles() {\r
+ return _processProfiles;\r
+ }\r
+\r
+ /**\r
+ * Return the profiles of all channels.\r
+ *\r
+ * @return profile of all channels\r
+ */\r
+ public HashMap<String, ChannelProfile> getChannelProfiles() {\r
+ return _channelProfiles;\r
+ }\r
+\r
+ /**\r
+ * Return the order in which processes write to channels.\r
+ *\r
+ * @return profile of all processes\r
+ */\r
+ public HashMap<String, Vector<String>> getProcessCommOrder() {\r
+ return _processCommOrder;\r
+ }\r
+\r
+ /**\r
+ * Return the channel to which the port with the specified name is\r
+ * connected.\r
+ *\r
+ * @param port port name\r
+ * @return name of connected channel\r
+ */\r
+ public String getChannel(String port) {\r
+ if (_inPortToChannelMapping.get(port) != null) {\r
+ return _inPortToChannelMapping.get(port);\r
+ } else if (_outPortToChannelMapping.get(port) != null) {\r
+ return _outPortToChannelMapping.get(port);\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Return the type of the channel with the specified name.\r
+ *\r
+ * @param port port name\r
+ * @return type of port\r
+ */\r
+ public String getPortType(String port) {\r
+ if (_inPortToChannelMapping.get(port) != null) {\r
+ return "INPUT";\r
+ } else if (_outPortToChannelMapping.get(port) != null) {\r
+ return "OUTPUT";\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Add a channel profile to the HashMap of channel profiles.\r
+ *\r
+ * @param channelName name of the channel\r
+ * @param capacity capacity of the channel\r
+ * @param portAType type of first port (either "o" or "i")\r
+ * @param processAName name of process connected to first port\r
+ * @param portAName name of first port\r
+ * @param portBType type of second port (either "o" or "i")\r
+ * @param processBName name of process connected to second port\r
+ * @param portBName name of second port\r
+ */\r
+ protected void addChannelProfile(String channelName, int capacity,\r
+ String portAType, String processAName, String portAName,\r
+ String portBType, String processBName, String portBName) {\r
+\r
+ ChannelProfile channelProfile =\r
+ new ChannelProfile(channelName, capacity);\r
+ _channelProfiles.put(channelName, channelProfile);\r
+\r
+ if (portAType.equals("o")) {\r
+ //first output port, then input port\r
+ _outPortToChannelMapping.put(portAName, channelName);\r
+ if (!(portBType.equals("i"))) {\r
+ System.err.println("Input file corrupt: each "\r
+ + "channel needs one input- and one "\r
+ + "output port.");\r
+ return;\r
+ }\r
+ _inPortToChannelMapping.put(portBName, channelName);\r
+ } else if (portAType.equals("i")) {\r
+ //first input port, then output port\r
+ _inPortToChannelMapping.put(portAName, channelName);\r
+ if (!(portBType.equals("o"))) {\r
+ System.err.println("Input file corrupt: each "\r
+ + "channel needs one input- and one "\r
+ + "output port.");\r
+ return;\r
+ }\r
+ _outPortToChannelMapping.put(portBName, channelName);\r
+ } else {\r
+ System.err.println("Input file corrupt: bad channel "\r
+ + "specification:");\r
+ System.err.println(channelName + " " + capacity + " "\r
+ + portAType + " " + processAName + " " + portAName\r
+ + " "\r
+ + portBType + " " + processBName + " " + portBName);\r
+ }\r
+ }\r
+\r
+ private BufferedReader _in = null;\r
+ protected int _lineCounter = 0;\r
+ HashMap<String, ProcessProfile> _processProfiles;\r
+ HashMap<String, ChannelProfile> _channelProfiles;\r
+ HashMap<String, String> _inPortToChannelMapping;\r
+ HashMap<String, String> _outPortToChannelMapping;\r
+ HashMap<String, Vector<String>> _processCommOrder;\r
+}\r
--- /dev/null
+/* $Id: Profiler.java 203 2010-10-11 08:59:47Z dchokshi $ */\r
+package dol.helper.profiler;\r
+\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.Vector;\r
+\r
+import dol.datamodel.XmlTag;\r
+import dol.datamodel.pn.Channel;\r
+import dol.datamodel.pn.Port;\r
+import dol.datamodel.pn.Process;\r
+import dol.datamodel.pn.ProcessNetwork;\r
+import dol.datamodel.pn.ProfilingConfiguration;\r
+\r
+\r
+/**\r
+ * DOL profiler main class. Reads in profile data and generates the\r
+ * profiling information.\r
+ */\r
+public class Profiler {\r
+\r
+ /**\r
+ * Constructor\r
+ */\r
+ public Profiler() {\r
+ }\r
+\r
+ /**\r
+ * @param name Name of the trace file\r
+ * @param pn The process network need to be annotated\r
+ */\r
+ public void profilePN(String name, ProcessNetwork pn) {\r
+ ProfileParser profileParser = new ProfileParser(name);\r
+ profileParser.parseProfile();\r
+\r
+ HashMap<String, ChannelProfile> channelProfiles =\r
+ profileParser.getChannelProfiles();\r
+ Iterator<String> iterator = channelProfiles.keySet().iterator();\r
+\r
+ while (iterator.hasNext()) {\r
+ ChannelProfile profile = channelProfiles.get(iterator.next());\r
+ Channel channel = pn.getChannel(profile.getName());\r
+ ProfilingConfiguration c = channel.getProfilingCfg(\r
+ _xt.getProfilingTotalReadData());\r
+ if (c == null) {\r
+ //no profiling present, add new one\r
+ c = new ProfilingConfiguration(\r
+ _xt.getProfilingTotalReadData());\r
+ c.setValue(Long.toString(profile.getTotalReadData()));\r
+ channel.getProfilingList().add(c);\r
+ } else {\r
+ // profiling already present, extend existing one\r
+ Long curr = Long.decode(c.getValue());\r
+ curr += profile.getTotalReadData();\r
+ c.setValue(Long.toString(curr));\r
+ }\r
+\r
+ c = channel.getProfilingCfg(_xt.getProfilingNumOfReads());\r
+ if (c == null) {\r
+ c = new ProfilingConfiguration(\r
+ _xt.getProfilingNumOfReads());\r
+ c.setValue(Integer.toString(profile.getNumOfReads()));\r
+ channel.getProfilingList().add(c);\r
+ } else {\r
+ Long curr = Long.decode(c.getValue());\r
+ curr += profile.getNumOfReads();\r
+ c.setValue(Long.toString(curr));\r
+ }\r
+\r
+ c = channel.getProfilingCfg(_xt.getProfilingNumOfWrites());\r
+ if (c == null) {\r
+ c = new ProfilingConfiguration(\r
+ _xt.getProfilingNumOfWrites());\r
+ c.setValue(Integer.toString(profile.getNumOfWrites()));\r
+ channel.getProfilingList().add(c);\r
+ } else {\r
+ Long curr = Long.decode(c.getValue());\r
+ curr += profile.getNumOfWrites();\r
+ c.setValue( Long.toString(curr) );\r
+ }\r
+ }\r
+\r
+ HashMap<String, ProcessProfile> processProfiles =\r
+ profileParser.getProcessProfiles();\r
+ iterator = processProfiles.keySet().iterator();\r
+\r
+ while (iterator.hasNext()) {\r
+ ProcessProfile profile = processProfiles.get(iterator.next());\r
+ Process process = pn.getProcess(profile.getName());\r
+ ProfilingConfiguration c = process.getProfilingCfg(\r
+ _xt.getProfilingNumOfFires());\r
+\r
+ if (c == null) {\r
+ c = new ProfilingConfiguration(\r
+ _xt.getProfilingNumOfFires());\r
+ c.setValue(Integer.toString(profile.getNumOfFires()));\r
+ process.getProfilingList().add(c);\r
+ } else {\r
+ int curr = Integer.valueOf(c.getValue());\r
+ curr += profile.getNumOfFires();\r
+ c.setValue(Integer.toString(curr));\r
+ }\r
+\r
+ HashMap<String, PortProfile> portProfiles =\r
+ profile.getPortProfiles();\r
+ Iterator<String> iteratorB = portProfiles.keySet().iterator();\r
+\r
+ while (iteratorB.hasNext()) {\r
+ PortProfile portProfile =\r
+ portProfiles.get(iteratorB.next());\r
+ String portName = getPNPortName(portProfile.getName(), profileParser, pn);\r
+ c = new ProfilingConfiguration(portName + ".accesses");\r
+ c.setValue(portProfile.getAccesses().toString());\r
+ process.getProfilingList().add(c);\r
+ c = new ProfilingConfiguration(portName + ".tokensize");\r
+ c.setValue(portProfile.getTokenSize().toString());\r
+ process.getProfilingList().add(c);\r
+ c = new ProfilingConfiguration(portName + ".initialAccesses");\r
+ c.setValue(Integer.toString(portProfile.getInitialAccesses()));\r
+ process.getProfilingList().add(c);\r
+ c = new ProfilingConfiguration(portName + ".initialtokensize");\r
+ c.setValue(portProfile.getInitialTokenSize().toString());\r
+ process.getProfilingList().add(c);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ *\r
+ */\r
+ protected String getPNPortName(String profilePortName,\r
+ ProfileParser parser, ProcessNetwork pn) {\r
+ Vector<Port> ports = pn.getChannel(parser.\r
+ getChannel(profilePortName)).getPortList();\r
+ for (int i = 0; i < ports.size(); i++) {\r
+ if (parser.getPortType(profilePortName).equals("INPUT") &&\r
+ ports.elementAt(i).isOutPort()) {\r
+ return ports.elementAt(i).getPeerPort().getName();\r
+ } else if (parser.getPortType(profilePortName).equals("OUTPUT") &&\r
+ ports.elementAt(i).isInPort()) {\r
+ return ports.elementAt(i).getPeerPort().getName();\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Main function\r
+ *\r
+ * @param args command line arguments. args[0] is the filename of\r
+ * the profile file. args[1] is the filename of the process network\r
+ * XML file.\r
+ */\r
+ public static void main(String[] args) {\r
+ //check command line parameters\r
+ if (args.length != 2) {\r
+ System.out.println("Usage: Profiler <trace> <pn>");\r
+ System.out.println();\r
+ return;\r
+ }\r
+\r
+ ProfileParser profileParser = new ProfileParser(args[0]);\r
+\r
+ //parse input file\r
+ profileParser.parseProfile();\r
+\r
+ //print the results\r
+ System.out.println("----- Channel Analyzer Report -----");\r
+ System.out.println("<channel name> <maximum fill level> "\r
+ + "<total amount of transferred data> "\r
+ + "<num of reads> <num of writes>");\r
+\r
+ HashMap<String, ChannelProfile> channelProfiles =\r
+ profileParser.getChannelProfiles();\r
+ Iterator<String> iterator = channelProfiles.keySet().iterator();\r
+\r
+ while (iterator.hasNext()) {\r
+ ChannelProfile profile = channelProfiles.get(iterator.next());\r
+ System.out.println( "<" + profile.getName() +\r
+ "> "\r
+ + profile.getMaxFillLevel() + " "\r
+ + profile.getTotalReadData() + " "\r
+ + profile.getNumOfReads() + " "\r
+ + profile.getNumOfWrites());\r
+ }\r
+ System.out.println();\r
+\r
+ System.out.println("----- Processnetwork Report -----");\r
+ System.out.println("<process name> <num of activations>");\r
+\r
+ HashMap<String, ProcessProfile> processProfiles =\r
+ profileParser.getProcessProfiles();\r
+ iterator = processProfiles.keySet().iterator();\r
+ while (iterator.hasNext()) {\r
+ ProcessProfile profile = processProfiles.get(iterator.next());\r
+ System.out.println( "<" + profile.getName()\r
+ + "> " + profile.getNumOfFires());\r
+ }\r
+ System.out.println();\r
+\r
+ /*\r
+ //another test\r
+ PNXmlParser parserPN = new PNXmlParser();\r
+ ProcessNetwork pn = parserPN.doParse(args[1]);\r
+ Profiler p = new Profiler();\r
+ p.profilePN(args[0], pn);\r
+ pn.accept(new PNXmlVisitor("processnetwork.xml"));\r
+ */\r
+ }\r
+\r
+ protected XmlTag _xt = XmlTag.getInstance();\r
+}\r
--- /dev/null
+/* $Id: Range.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.helper.profiler;\r
+\r
+import java.util.Collections;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * Tuple of numbers representing an integer range. Except for an\r
+ * uninitialized range when using the default constructor, the\r
+ * range values are sorted, such that {@link #getLower()} returns\r
+ * the lower bound and {@link #getUpper()} the upper bound of the\r
+ * range.\r
+ */\r
+public class Range {\r
+\r
+ protected int _lower = Integer.MAX_VALUE;\r
+ protected int _upper = Integer.MIN_VALUE;\r
+ protected int _initialLower = Integer.MAX_VALUE;\r
+ protected int _initialUpper = Integer.MIN_VALUE;\r
+ public static final String DELIMITER = "-";\r
+\r
+ /**\r
+ * Default constructor. When merging this range with another\r
+ * range, always the resulting range will have the values of\r
+ * the other range.\r
+ */\r
+ public Range() {\r
+ }\r
+\r
+ /**\r
+ * Construct a range with equal upper and lower bound.\r
+ *\r
+ * @param value upper and lower bound of range\r
+ */\r
+ public Range(int value) {\r
+ _lower = value;\r
+ _upper = value;\r
+ _initialLower = _lower;\r
+ _initialUpper = _upper;\r
+ }\r
+\r
+ /**\r
+ * Construct a range with the two given bounds.\r
+ *\r
+ * @param valueA upper or lower bound\r
+ * @param valueB upper or lower bound\r
+ */\r
+ public Range(int valueA, int valueB) {\r
+ _lower = Math.min(valueA, valueB);\r
+ _upper = Math.max(valueA, valueB);\r
+ _initialLower = _lower;\r
+ _initialUpper = _upper;\r
+ }\r
+\r
+ /**\r
+ * Construct a range with upper and lower bounds that are the minimum\r
+ * and maximum of the given vector.\r
+ *\r
+ * @param values vector whose minimum and maximum value are used as\r
+ * bounds for the range\r
+ */\r
+ public Range(Vector<Integer> values) {\r
+ if (values == null || values.size() == 0) {\r
+ return;\r
+ }\r
+\r
+ _lower = Collections.min(values);\r
+ _upper = Collections.max(values);\r
+ }\r
+\r
+ /**\r
+ * Return lower bound of this range.\r
+ *\r
+ * @return lower bound\r
+ */\r
+ protected int getLower() {\r
+ return _lower;\r
+ }\r
+\r
+ /**\r
+ * Return upper bound of this range.\r
+ *\r
+ * @return upper bound\r
+ */\r
+ protected int getUpper() {\r
+ return _upper;\r
+ }\r
+\r
+ /**\r
+ * Combine range with another range. The lower bound of the range is\r
+ * the minimum of the lower bounds of this range and the other range.\r
+ * The upper bound of the range is the maximum of the upper bounds of\r
+ * this range and the other range.\r
+ *\r
+ * @param range to combine with this range\r
+ */\r
+ public void merge(Range range) {\r
+ if (range == null)\r
+ return;\r
+\r
+ _lower = Math.min(_lower, range.getLower());\r
+ _upper = Math.max(_upper, range.getUpper());\r
+ }\r
+\r
+ /**\r
+ * Combine range with a value. The lower bound of the range is\r
+ * the minimum of the lower bound of this range and the value.\r
+ * The upper bound of the range is the maximum of the upper bound of\r
+ * this range and the value.\r
+ *\r
+ * @param value integer value to combine with this range\r
+ */\r
+ public void merge(int value) {\r
+ _lower = Math.min(_lower, value);\r
+ _upper = Math.max(_upper, value);\r
+ }\r
+\r
+ /**\r
+ * Create a string representation of the range.\r
+ *\r
+ * @return string representation of the range\r
+ */\r
+ public String toString() {\r
+ if (_upper == _lower)\r
+ return Integer.toString(_upper);\r
+ return _lower + DELIMITER + _upper;\r
+ }\r
+\r
+ /**\r
+ * Create a range based on a string representation of a range.\r
+ *\r
+ * @param string representation of a range\r
+ * @return range\r
+ * @throws IllegalArgumentException\r
+ */\r
+ public static Range valueOf(String string) throws IllegalArgumentException {\r
+ java.util.regex.Pattern pattern =\r
+ java.util.regex.Pattern.compile(\r
+ "([-]?[0-9]+)[" + DELIMITER + "]?([-]?[0-9]+)?");\r
+ java.util.regex.Matcher m = pattern.matcher(string);\r
+ if (!m.matches()) {\r
+ throw new IllegalArgumentException("String does not " +\r
+ "represent a range.");\r
+ }\r
+ return new Range(Integer.valueOf(m.group(1)),\r
+ Integer.valueOf(m.group(2)));\r
+ }\r
+\r
+ /**\r
+ * Reset this range to the values it had when it has been constructed.\r
+ */\r
+ public void reset() {\r
+ _lower = _initialLower;\r
+ _upper = _initialUpper;\r
+ }\r
+\r
+ /**\r
+ * Test cases for range class.\r
+ */\r
+ public static void main(String args[]) throws Exception {\r
+ Range a = new Range(1);\r
+ System.out.println(a);\r
+\r
+ Range b = new Range(1, 3);\r
+ System.out.println(b);\r
+\r
+ Range c = new Range(4, 3);\r
+ System.out.println(c);\r
+\r
+ b.merge(c);\r
+ System.out.println(b);\r
+\r
+ Range d = Range.valueOf("-123" + Range.DELIMITER + "-456");\r
+ System.out.println(d);\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/* $Id: VSPLogFileProfiler.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.helper.profiler;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.FileReader;\r
+import java.io.IOException;\r
+import java.util.StringTokenizer;\r
+\r
+import dol.datamodel.pn.Process;\r
+import dol.datamodel.pn.ProcessNetwork;\r
+import dol.datamodel.pn.ProfilingConfiguration;\r
+\r
+/**\r
+ * Class for parsing a file with profiling info and annotate it to a\r
+ * process network.\r
+ */\r
+public class VSPLogFileProfiler {\r
+\r
+ /**\r
+ * Parse the given file and annotate the data to the given process\r
+ * network.\r
+ *\r
+ * @param filename file with profiling info\r
+ * @param pn processnetwork to annotate\r
+ */\r
+ public static void annotateProcessNetwork(String filename,\r
+ ProcessNetwork pn) {\r
+ try {\r
+ BufferedReader reader = new BufferedReader(\r
+ new FileReader(filename));\r
+ String line;\r
+ while ((line = reader.readLine()) != null) {\r
+ StringTokenizer tokenizer =\r
+ new StringTokenizer(line, " ");\r
+ if (tokenizer.countTokens() == 2) {\r
+ continue;\r
+ }\r
+ else if (tokenizer.countTokens() <= 2) {\r
+ System.out.println("Warning: Each line in the log "\r
+ + "file should have the following form:"\r
+ + System.getProperty("line.separator")\r
+ + "processname config_name config_value"\r
+ + System.getProperty("line.separator")\r
+ + "Ignoring the non-conforming line:"\r
+ + System.getProperty("line.separator")\r
+ + line);\r
+ continue;\r
+ }\r
+ String processname = tokenizer.nextToken();\r
+ Process process = pn.getProcess(processname);\r
+ if (process == null) {\r
+ System.out.println("Warning: Could not find process "\r
+ + processname + " in processnetwork "\r
+ + pn.getName() + ". Ignore configuration "\r
+ + "statement in file " + filename + ".");\r
+ continue;\r
+ }\r
+ ProfilingConfiguration config =\r
+ new ProfilingConfiguration(tokenizer.nextToken());\r
+ String value = "";\r
+ while (tokenizer.hasMoreTokens()) {\r
+ value += tokenizer.nextToken() + " ";\r
+ }\r
+ config.setValue(value.trim());\r
+ config.setParentResource(process);\r
+ process.getProfilingList().add(config);\r
+ }\r
+ }\r
+ catch (IOException e) {\r
+ System.out.println(e);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/* $Id: WorkloadAnnotator.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.profiler;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Vector;
+
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.ProfilingConfiguration;
+import dol.parser.xml.pnschema.PNXmlParser;
+import dol.visitor.xml.PNXmlVisitor;
+
+public class WorkloadAnnotator {
+
+ /**
+ *
+ * @param args
+ */
+ public static void main(String[] args) {
+ String logFile = "workload.txt";
+ String pnFileIn = "processnetwork.xml";
+ String pnFileOut = "processnetwork.xml";
+
+ try {
+ if (args.length > 2) {
+ pnFileIn = args[0];
+ logFile = args[1];
+ pnFileOut = args[1];
+ } else if (args.length == 2) {
+ pnFileIn = args[0];
+ logFile = args[1];
+ } else if (args.length == 1) {
+ pnFileIn = args[0];
+ }
+
+ PNXmlParser parserPN = new PNXmlParser();
+ ProcessNetwork pn = parserPN.doParse(pnFileIn);
+
+ WorkloadAnnotator.annotateProcessNetwork(logFile, pn);
+ StringBuffer b = new StringBuffer();
+ pn.accept(new PNXmlVisitor(b));
+ FileWriter out = new FileWriter(pnFileOut);
+ out.write(b.toString());
+ out.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param workloadFileName
+ * @param pn
+ * @throws IOException
+ */
+ public static void annotateProcessNetwork(String workloadFileName,
+ ProcessNetwork pn) throws IOException {
+ for (Process p : pn.getProcessList()) {
+ Vector<ProfilingConfiguration> v = p.getProfilingList();
+ if (v == null) {
+ p.setProfilingList(new Vector<ProfilingConfiguration>());
+ }
+ }
+
+ BufferedReader in = new BufferedReader(new FileReader(workloadFileName));
+ String line, process, name, value;
+ while ((line = in.readLine()) != null) {
+ if (line.startsWith("wced_")) {
+ process = line.substring("wced_".length()).trim();
+ name = "WCET";
+
+ } else if (line.startsWith("bced_")) {
+ process = line.substring("bced_".length()).trim();
+ name = "BCET";
+
+ } else if (line.startsWith("workload_upper_")) {
+ process = line.substring("workload_upper_".length()).
+ trim();
+ name = "WORKLOAD_UPPER";
+
+ } else if (line.startsWith("workload_lower_")) {
+ process = line.substring("workload_lower_".length()).
+ trim();
+ name = "WORKLOAD_LOWER";
+
+ } else {
+ continue;
+ }
+ process = process.substring(0, process.length() - 1).trim();
+
+ in.readLine();
+ value = in.readLine().trim();
+
+ ProfilingConfiguration pc = new ProfilingConfiguration(name);
+ pc.setValue(value);
+ pn.getProcess(process).getProfilingList().add(pc);
+ }
+ }
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Profiler to extract parameters from a profiling file.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: XMLValidator.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.validator;
+
+import java.io.IOException;
+
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+/**
+ * Class to check well-formedness and validity of XML documents.
+ */
+public class XMLValidator {
+
+ /**
+ * Check the well-formedness and validity of an XML document.
+ * The file is checked against the schema which is referenced from
+ * within the file. When the document is an XML schema, it is checked
+ * against <a href="http://www.w3.org/2001/XMLSchema.xsd"
+ * target="_blank">http://www.w3.org/2001/XMLSchema.xsd</a>.
+ *
+ * @param filename filename of the file to be checked
+ */
+ public static boolean isValid(String filename) {
+ SAXBuilder builder = new SAXBuilder(true);
+ builder.setFeature("http://xml.org/sax/features/validation",
+ true);
+ builder.setFeature("http://apache.org/xml/features/validation/"
+ + "schema", true);
+ builder.setFeature("http://apache.org/xml/features/validation/"
+ + "schema-full-checking", true);
+ builder.setProperty("http://apache.org/xml/properties/schema/"
+ + "external-schemaLocation",
+ "http://www.w3.org/2001/XMLSchema "
+ + "http://www.w3.org/2001/XMLSchema.xsd "
+ + dol.util.SchemaLocation.getExternalSchemaLocation());
+ try {
+ builder.build(filename);
+ }
+ catch (JDOMException e) {
+ System.out.println("Found an error in " + filename + ".");
+ System.out.println(e.getMessage());
+ System.out.println("");
+ return false;
+ }
+ catch (IOException e) {
+ System.out.println("Found an error in " + filename + ".");
+ System.out.println(e.getMessage());
+ System.out.println("");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Main function. We might extend the validator to validate different
+ * kind of XMLs based on different schemas.
+ *
+ * @param args The command line argument.
+ */
+ public static void main(String[] args) {
+
+ /* Check command line parameters */
+ /* maybe add options to check both external/internal schema */
+ if (args.length != 1) {
+ System.out.println("Usage: XMLValidator <file>");
+ System.out.println();
+ return;
+ }
+
+ if (XMLValidator.isValid(args[0])){
+ System.out.println(args[0] + " is valid.");
+ } else {
+ System.exit(1);
+ }
+ }
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Utilities to check well-formedness and validity of XML documents.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: Main.java 203 2010-10-11 08:59:47Z dchokshi $ */
+package dol.main;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import dol.check.SanityCheck;
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.helper.profiler.Profiler;
+import dol.helper.profiler.VSPLogFileProfiler;
+import dol.helper.profiler.WorkloadAnnotator;
+import dol.parser.xml.archischema.ArchiXmlParser;
+import dol.parser.xml.mapschema.MapXmlParser;
+import dol.parser.xml.pnschema.PNXmlParser;
+import dol.util.CodePrintStream;
+import dol.visitor.PipeAndFilter.PipeAndFilterVisitor;
+import dol.visitor.cell.CellVisitor;
+import dol.visitor.dot.ArchDotVisitor;
+import dol.visitor.dot.MapDotVisitor;
+import dol.visitor.dot.PNDotVisitor;
+import dol.visitor.hds.HdsVisitor;
+import dol.visitor.hdsd.HdsdVisitor;
+import dol.visitor.protothread.ProtothreadVisitor;
+import dol.visitor.rtems.RtemsVisitor;
+import dol.visitor.systemC.PNSystemCVisitor;
+import dol.visitor.xml.PNXmlVisitor;
+import dol.visitor.yapi.YapiVisitor;
+
+/**
+ * Distributed Operating Layer (DOL)
+ *
+ * This class is the main controlling part of DOL. In this class, the
+ * command line options are processed, the input and output files are set,
+ * and the complete compilation cycle is done. Also, this class is the
+ * final responder to exceptions occurring within the DOL.
+ */
+public class Main {
+
+ /**
+ * The main method of this class
+ *
+ * @param args The arguments to provide to DOL.
+ */
+ public static void main(String[] args) {
+
+ _ui = UserInterface.getInstance();
+
+ try {
+ new Options(args);
+ } catch (NumberFormatException e) {
+ System.out.println("Error in Command line options: "
+ + " the numerial format for an argument is"
+ + " incorrect. Message: "
+ + e.getMessage());
+ System.exit(-1);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Error in Command line option: "
+ + e.getMessage());
+ System.exit(-1);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ System.exit(-1);
+ }
+
+ try {
+ //loader
+
+ //load process network specification from XML
+ if (_ui.getNetworkFileName() != null) {
+ PNXmlParser parserPN = new PNXmlParser();
+ _pn = parserPN.doParse(_ui.getNetworkFileName());
+ }
+
+ //load architecture specification from XML
+ if (_ui.getPlatformFileName() != null) {
+ ArchiXmlParser parserArch = new ArchiXmlParser();
+ _architecture = parserArch.doParse(
+ _ui.getPlatformFileName());
+
+ //not useful (archiPathFinderVisitor not functional)
+ //_architecture.setArchiConnections();
+ //_architecture.accept(new dol.visitor.pathFinder.
+ // archiPathFinderVisitor());
+ //_architecture.accept(new dol.visitor.pathFinder.
+ // archiPathPrinterVisitor());
+ }
+
+ //load mapping specification from XML
+ if ((_pn != null) && (_architecture != null)
+ && _ui.getMappingFileName() != null) {
+ MapXmlParser parserMap = new MapXmlParser(_pn, _architecture);
+ _mapping = parserMap.doParse(_ui.getMappingFileName());
+ }
+
+ //sanity check
+ if (_ui.getCheckFlag()){
+ System.out.println("Consistency check:");
+ //check process network
+ if (_pn != null)
+ SanityCheck.getInstance().checkPN(_pn);
+
+ //check architecture
+ if (_architecture != null)
+ SanityCheck.getInstance().checkArch(_architecture);
+
+ //check mapping
+ if (_mapping != null)
+ SanityCheck.getInstance().checkMap(_mapping);
+
+ System.out.println(" -- Consistency check [Finished]");
+ System.out.println();
+ }
+
+ // analyze profiling data and fill into pn
+ if (_ui.getProfilingFlag() && (_pn != null)) {
+ System.out.println(" -- ProcessNetwork profiling");
+ Profiler p = new Profiler();
+ p.profilePN(_ui.getTraceName(), _pn);
+ System.out.println(" -- Profiling [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getVspLogFlag() && (_pn != null)) {
+ System.out.println("VSP log file back-annotation:");
+ VSPLogFileProfiler.annotateProcessNetwork(
+ _ui.getVspLogFileName(), _pn);
+ System.out.println(" -- Back-annotation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getWorkloadFlag() && (_pn != null)) {
+ System.out.println("Workload file back-annotation:");
+ WorkloadAnnotator.annotateProcessNetwork(
+ _ui.getWorkloadFileName(), _pn);
+ System.out.println(" -- Back-annotation [Finished]");
+ System.out.println();
+ }
+
+ //Generator
+ CodePrintStream printStream;
+
+ if (_ui.getDottyFlag()) {
+ OutputStream file = new FileOutputStream(_ui.getDottyFileName());
+ printStream = new CodePrintStream(file);
+ if (_mapping != null)
+ {
+ System.out.println("Generating Mapping in Dotty format:");
+ _mapping.accept(new MapDotVisitor(printStream));
+ }
+ else if (_pn != null)
+ {
+ System.out.println("Generating ProcessNetwork in Dotty format:");
+ _pn.accept(new PNDotVisitor(printStream));
+ }
+ else if (_architecture!=null) {
+ System.out.println("Generating Architecture in Dotty format:");
+ _architecture.registerRWPath2Resource();
+ _architecture.accept(new ArchDotVisitor(printStream));
+ }
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getXmlGenFlag() && (_pn != null)) {
+ System.out.println("Generating ProcessNetwork in XML format:");
+ StringBuffer buffer = new StringBuffer();
+ _pn.accept(new PNXmlVisitor(buffer));
+ try {
+ java.io.BufferedWriter writer =
+ new java.io.BufferedWriter(
+ new java.io.FileWriter(_ui.getOutputFileName()));
+ writer.write(buffer.toString());
+ writer.close();
+ } catch (java.io.IOException e) {
+ System.out.println(" -- DOL caught an exception while "
+ + "creating XML file: " + e.getMessage());
+ e.printStackTrace(System.out);
+ }
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getSystemCFlag() && (_pn != null)) {
+ System.out.println("Generating SystemC package:");
+ _pn.accept(new PNSystemCVisitor(_ui.getCodeDirectoryName()));
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getPipeAndFilterFlag() && (_pn != null)) {
+ System.out.println("Generating PipeAndFilter package:");
+ _pn.accept(new PipeAndFilterVisitor(
+ _ui.getPipeAndFilterCodeDirectoryName()));
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getProtothreadFlag() && (_pn != null)) {
+ System.out.println("Generating protothread package:");
+ _pn.accept(new ProtothreadVisitor(
+ _ui.getProtothreadCodeDirectoryName()));
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getRtemsFlag() && (_pn != null)) {
+ String bsp = _ui.getRtemsBSP();
+ System.out.println("Generating RTEMS-" + bsp + " package:");
+ _pn.accept(new RtemsVisitor(
+ _ui.getRtemsCodeDirectoryName()));
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getCbeFlag() && (_pn != null)) {
+ System.out.println("Generating Cell-package:");
+ _pn.accept(new CellVisitor(
+ _ui.getCbeCodeDirectoryName()));
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getYapiFlag() && (_pn != null)) {
+ System.out.println("Generating YAPI-package:");
+ _pn.accept(new YapiVisitor(
+ _ui.getYapiCodeDirectoryName()));
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ if (_ui.getHdsFlag() && (_pn != null)) {
+ System.out.println("Generating HdS package:");
+ if ((_pn!=null) && (_architecture!=null) && (_mapping!=null)) {
+ System.out.println("Generating distributed HdS package:");
+ // Hds with networking supportSAXException
+ _mapping.accept(new HdsdVisitor(_ui.getHdsCodeDirectoryName()));
+
+ } else {
+ // Hds without networking support
+ _pn.accept(new HdsVisitor(_ui.getHdsCodeDirectoryName()));
+ }
+ System.out.println(" -- Generation [Finished]");
+ System.out.println();
+ }
+
+ }
+ catch (NumberFormatException e) {
+ System.out.println(" ERROR Occured in DOL: " + e.getMessage());
+ e.printStackTrace(System.out);
+ }
+ catch (Exception e) {
+ System.out.println(" DOL caught an exception: " + e.getMessage());
+ e.printStackTrace(System.out);
+ }
+ }
+
+ protected static ProcessNetwork _pn = null;
+ protected static Architecture _architecture = null;
+ protected static Mapping _mapping = null;
+ protected static UserInterface _ui = null;
+}
--- /dev/null
+/* $Id: Options.java 203 2010-10-11 08:59:47Z dchokshi $ */
+package dol.main;
+
+/**
+ * This class handles the command line options. It checks if an option is
+ * valid, and if so, it calls the appropriate method in the UserInterface,
+ * that reflects the global setting of DOL.
+ */
+public class Options {
+
+ /**
+ * Parse the command-line arguments, creating models as specified. Then
+ * execute each model that contains a manager.
+ *
+ * @param args
+ * The command-line arguments.
+ * @exception IllegalArgumentException
+ * MyException If such and such occurs
+ * @throws IllegalArgumentException
+ * if an illegal argument is found on the command line.
+ */
+ public Options(String args[]) throws IllegalArgumentException, NumberFormatException {
+ _ui = UserInterface.getInstance();
+ if(args != null) {
+ _parseArgs(args);
+ }
+ }
+
+ /**
+ * Parse the command-line arguments.
+ *
+ * @param args The arguments to be parsed
+ *
+ * @throws IllegalArgumentException
+ * if an illegal argument is found on the command line.
+ */
+ protected void _parseArgs(String args[]) throws IllegalArgumentException,
+ NumberFormatException {
+ if(args.length > 0) {
+ for(int i = 0; i < args.length; i++ ) {
+ String arg = args[i];
+ if(_parseArg(arg) == false ) {
+ if(arg.startsWith("-") && i < args.length - 1 ) {
+ if(arg.equals("--platform") || arg.equals("-p") ) {
+ _ui.setPlatformFileName(args[++i]);
+ } else if(arg.equals("--processnetwork") || arg.equals("-P") ) {
+ _ui.setNetworkFileName(args[++i]);
+ } else if(arg.equals("--mapping") || arg.equals("-m") ) {
+ _ui.setMappingFileName(args[++i]);
+ } else if(arg.equals("--scheduler") || arg.equals("-s") ) {
+ _ui.setSchedulerFileName(args[++i]);
+ } else if(arg.equals("--systemC") || arg.equals("-C") ) {
+ _ui.setCodeDirectoryName(args[++i]);
+ _ui.setSystemCFlag();
+ } else if(arg.equals("--HdS") || arg.equals("-H") ) {
+ _ui.setHdsCodeDirectoryName(args[++i]);
+ _ui.setHdsFlag();
+ } else if(arg.startsWith("--rtems") || arg.startsWith("-R") ) {
+ String bsp = arg;
+ bsp = bsp.replaceAll("--rtems" , "");
+ bsp = bsp.replaceAll("-R", "");
+ if (bsp.equals("")) {
+ _ui.setRtemsBSP("pc386");
+ } else if (bsp.equals("pc386") || bsp.equals("mparm")) {
+ _ui.setRtemsBSP(bsp);
+ } else {
+ throw new IllegalArgumentException(
+ "Board support package \"" + bsp
+ + "\" not supported by code generation.");
+ }
+ _ui.setRtemsCodeDirectoryName(args[++i]);
+ _ui.setRtemsFlag();
+ } else if(arg.equals("--PaF") || arg.equals("-PF") ) {
+ _ui.setPipeAndFilterCodeDirectoryName(args[++i]);
+ _ui.setPipeAndFilterFlag();
+ } else if(arg.equals("--protothread") || arg.equals("-PT") ) {
+ _ui.setProtothreadCodeDirectoryName(args[++i]);
+ _ui.setProtothreadFlag();
+ } else if(arg.equals("--dotty") || arg.equals("-D")) {
+ _ui.setDottyFileName(args[++i]);
+ } else if(arg.equals("--profiling") || arg.equals("-T")) {
+ _ui.setTraceName(args[++i]);
+ _ui.setProfilingFlag();
+ } else if (arg.equals("--vsplog") || arg.equals("-L")) {
+ _ui.setVspLogFileName(args[++i]);
+ _ui.setVspLogFlag();
+ } else if (arg.equals("--workload") || arg.equals("-W")) {
+ _ui.setWorkloadFileName(args[++i]);
+ _ui.setWorkloadFlag();
+ } else if(arg.equals("--xmlGen") || arg.equals("-G")) {
+ _ui.setOutputFileName(args[++i]);
+ _ui.setXmlGenFlag();
+ } else if(arg.equals("--cbe") || arg.equals("-CBE")) {
+ _ui.setCbeCodeDirectoryName(args[++i]);
+ _ui.setCbeFlag();
+ } else if(arg.equals("--yapi") || arg.equals("-Y")) {
+ _ui.setYapiCodeDirectoryName(args[++i]);
+ _ui.setYapiFlag();
+ } else {
+ throw new IllegalArgumentException("Unrecognized option: " + arg);
+ }
+ } else {
+ throw new IllegalArgumentException("Unrecognized option: " + arg);
+ }
+ }
+ }
+ } else {
+ throw new IllegalArgumentException(_usage());
+ }
+ }
+
+ /**
+ * Parse a single commandline argument.
+ *
+ * @param arg commandline argument
+ * @return true if the argument is understood, false otherwise
+ * @throws IllegalArgumentExcecption thrown if an illegal argument is
+ * found on the command line.
+ */
+ protected boolean _parseArg(String arg) throws IllegalArgumentException {
+ if(arg.equals("--help") || arg.equals("-h") ) {
+ //throw new IllegalArgumentException(_usage());
+ System.out.println(_usage() );
+ System.exit(0);
+ } else if(arg.equals("--version") || arg.equals("-V") ) {
+ System.out.println("DOL version 0.0.1\n");
+ System.exit(0);
+ } else if(arg.equals("--verbose") || arg.equals("-v") ) {
+ _ui.setVerboseFlag();
+ } else if(arg.equals("--check") || arg.equals("-c")) {
+ _ui.setCheckFlag();
+ } else if(arg.equals("--debug")) {
+ _ui.setDebugFlag();
+ } else if(arg.equals("")) { // Ignore blank argument.
+ } else { // Argument not recognized.
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return a string summarizing the command-line arguments.
+ *
+ * @return A usage string.
+ */
+ protected String _usage() {
+ String result = "Usage: " + _commandTemplate + "\n\n"
+ + "Options:\n";
+
+ int i;
+ for(i = 0; i < _commandOptions.length; i++) {
+ result += " " + _commandOptions[i][0] + "\tabbr["
+ + _commandOptions[i][1] + " " + _commandOptions[i][2]
+ + "]\n";
+ }
+ result += "\nBoolean flags:\n";
+ for(i = 0; i < _commandFlags.length; i++) {
+ result += " " + _commandFlags[i][0] + "\tabbr["
+ + _commandFlags[i][1] + "]\n";
+ }
+ return result;
+ }
+
+ /**
+ * The command-line options that are either present or not. Give the full
+ * name preceded with '--' and abbreviated version.
+ */
+ protected String _commandFlags[][] = {
+ { "--check ", "-c" },
+ { "--flatten ", "-F" },
+ { "--help ", "-h" },
+ { "--version ", "-V" },
+ { "--verbose ", "-v" },
+ { "--debug ", "none" },
+ };
+
+ /**
+ * The command-line options that take arguments.
+ */
+ protected String _commandOptions[][] = {
+ { "--platform ", "-p ", "<FileName>" },
+ { "--processnetwork", "-P ", "<FileName>" },
+ { "--mapping ", "-m ", "<FileName>" },
+ { "--scheduler ", "-s ", "<FileName>" },
+ { "--dotty ", "-D ", "<FileName>" },
+ { "--xmlGen ", "-G", "<FileName>" },
+ { "--systemC ", "-C ", "<DirectoryName>" },
+ { "--HdS ", "-H ", "<DirectoryName>" },
+ { "--PaF ", "-PF", "<DirectoryName>" },
+ { "--rtems ", "-R", "<DirectoryName>" },
+ { "--protothread ", "-PT", "<DirectoryName>" },
+ { "--profiling ", "-T", "<trace FileName>" },
+ { "--vsplog ", "-L", "<log FileName>" },
+ { "--cbe ", "-CBE", "<DirectoryName>" },
+ { "--yapi ", "-Y", "<DirectoryName>" }
+ };
+
+ /**
+ * The form of the command line.
+ */
+ protected String _commandTemplate = "dol [ options ]";
+
+ /**
+ * The UserInterface object.
+ */
+ protected UserInterface _ui = null;
+}
--- /dev/null
+/* $Id: UserInterface.java 203 2010-10-11 08:59:47Z dchokshi $ */
+package dol.main;
+
+import java.util.ResourceBundle;
+
+/**
+ * Class to store commandline arguments and flags.
+ */
+public class UserInterface {
+
+ /**
+ * Get a single instance of the UserInterface object.
+ */
+ private final static UserInterface _instance = new UserInterface();
+
+
+ // the platform file name
+ private String _platformFileName = null;
+
+ // the process network file name
+ private String _networkFileName = null;
+
+ // the mapping file name
+ private String _mappingFileName = null;
+
+ // the scheduler file name
+ private String _schedulerFileName = null;
+
+ // the dotty file name
+ private String _dottyFileName = "dotty.dot";
+
+ // the systemc directory name
+ private String _codeDirectoryName = "nonamePackage";
+
+ // the pipeandfilter directory name
+ private String _pipeCodeDirectoryName = "nonamePipePackage";
+
+ // the hds directory name
+ private String _hdsCodeDirectoryName = "nonameHdsPackage";
+
+ // the RTEMS directory name
+ private String _rtemsCodeDirectoryName = "nonameHdsPackage";
+
+ // the RTEMS board support package for which code is generated
+ private String _rtemsBSP = "pc386";
+
+ // the protothread directory name
+ private String _protothreadCodeDirectoryName = "nonameHdsPackage";
+
+ // the CBE directory name
+ private String _cbeCodeDirectoryName = "nonameCbePackage";
+
+ // the Yapi directory name
+ private String _yapiCodeDirectoryName = "nonameYapiPackage";
+
+
+ // trace filename
+ private String _traceName = "";
+
+ // the xml generation flag
+ private boolean _xmlGen = false;
+
+ // the trace flag
+ private boolean _profiling = false;
+
+ // the verbose flag
+ private boolean _verbose = false;
+
+ // the vsp log flag
+ private boolean _vsplog = false;
+
+ // the name of the vsp log file
+ private String _vspLogFileName = "";
+
+ // the workload annotation flag
+ private boolean _workload = false;
+
+ // the name of the workload file produces by Matlab
+ private String _workloadFileName = "";
+
+ // the SystemC flag
+ private boolean _systemC = false;
+
+ // the PipeAndFilter flag
+ private boolean _pipeAndFilter = false;
+
+ // the HdS flag
+ private boolean _hds = false;
+
+ // the RTEMS flag
+ private boolean _rtems = false;
+
+ // the CBE flag
+ private boolean _cbe = false;
+
+ // the YAPI flag
+ private boolean _yapi = false;
+
+ // the RTEMS flag
+ private boolean _protothread = false;
+
+ // the debug flag
+ private boolean _debug = false;
+
+ // the dotty flag
+ private boolean _dotty = false;
+
+ // the check flag
+ private boolean _check = false;
+
+ // the path finder flag
+ private boolean _archiPaths = true;
+
+ // the basepath name
+ private String _basePath = ".";
+
+ // the filename
+ private String _outputFileName = "";
+
+ // ResourceBundle
+ private ResourceBundle _rb;
+ private String _rbFileName = "dol";
+
+
+ public final String getMySystemCLib() {
+ /*
+ return _rb.getString("DOL_path") + getDelimiter()
+ + "src" + getDelimiter() + "dol" + getDelimiter()
+ + "visitor" + getDelimiter() + "systemC" + getDelimiter()
+ + "lib";
+ */
+
+ return this.getClass().getResource(
+ "/dol/visitor/systemC/lib").getFile();
+ }
+
+ public final String getVisitorDir(){
+ return this.getClass().getResource("/dol/visitor/").getFile();
+ }
+
+ public final String getDOLPath() { return _rb.getString("DOL_path"); }
+ public final String getSystemCINC(){return _rb.getString("SYSTEMC_INC");}
+ public final String getSystemCLIB(){return _rb.getString("SYSTEMC_LIB");}
+
+ /**
+ * returns the singleton instance of this class.
+ *
+ * @return The instance value
+ */
+ public final static UserInterface getInstance() {
+ return _instance;
+ }
+
+ /**
+ * Get the name of the platform file.
+ *
+ * @return The platformFileName value
+ */
+ public final String getPlatformFileName() {
+ return _platformFileName;
+ }
+
+ /**
+ * Set the name of the platform file.
+ *
+ * @param platformFileName
+ * The new platformFileName value
+ */
+ public final void setPlatformFileName(String platformFileName) {
+ _platformFileName = platformFileName;
+ }
+
+ /**
+ * Get the name of the process network file.
+ *
+ * @return The networkFileName value
+ */
+ public final String getNetworkFileName() {
+ return _networkFileName;
+ }
+
+ /**
+ * Set the name of the process network file.
+ *
+ * @param networkFileName
+ * The new networkFileName value
+ */
+ public final void setNetworkFileName(String networkFileName) {
+ _networkFileName = networkFileName;
+ }
+
+ /**
+ * Get the name of the mapping file.
+ *
+ * @return The mappingFileName value
+ */
+ public final String getMappingFileName() {
+ return _mappingFileName;
+ }
+
+ /**
+ * Set the name of the mapping file.
+ *
+ * @param mappingFileName
+ * The new mappingFileName value
+ */
+ public final void setMappingFileName(String mappingFileName) {
+ _mappingFileName = mappingFileName;
+ }
+
+
+ /**
+ * Get the name of the scheduler file.
+ *
+ * @return The schedulerFileName value
+ */
+ public final String getSchedulerFileName() {
+ return _schedulerFileName;
+ }
+
+ /**
+ * Set the name of the scheduler file.
+ *
+ * @param schedulerFileName
+ * The new schedulerFileName value
+ */
+ public final void setSchedulerFileName(String schedulerFileName) {
+ _schedulerFileName = schedulerFileName;
+ }
+
+
+ /**
+ * Get the name of the dotty file..
+ *
+ * @return The dottyFileName value
+ */
+ public final String getDottyFileName() {
+ return _dottyFileName;
+ }
+
+ /**
+ * Set the name of the directory where the SystemC code shall be generated.
+ *
+ * @param dottyFileName The dotty file name.
+ */
+ public final void setDottyFileName(String dottyFileName) {
+ _dottyFileName = dottyFileName;
+ setDottyFlag();
+ }
+
+
+ /**
+ * Get the name of the SystemC directory.
+ *
+ * @return The directory name of the SystemC directory
+ */
+ public final String getCodeDirectoryName() {
+ return _codeDirectoryName;
+ }
+
+ /**
+ * Set the name of the directory where the SystemC code shall be generated.
+ *
+ * @param codeDirectoryName The code directory
+ */
+ public final void setCodeDirectoryName(String codeDirectoryName) {
+ _codeDirectoryName = codeDirectoryName;
+ }
+
+ /**
+ * Get the name of the PipeAndFilter directory.
+ *
+ * @return The directory name of the PipeAndFilter directory
+ */
+ public final String getPipeAndFilterCodeDirectoryName() {
+ return _pipeCodeDirectoryName;
+ }
+
+ /**
+ * Set the name of the directory where the Hds code shall be generated.
+ *
+ * @param codeDirectoryName The code directory
+ */
+ public final void setPipeAndFilterCodeDirectoryName(String codeDirectoryName) {
+ _pipeCodeDirectoryName = codeDirectoryName;
+ }
+
+ /**
+ * Get the name of the Hds directory.
+ *
+ * @return The directory name of the Hds directory
+ */
+ public final String getHdsCodeDirectoryName() {
+ return _hdsCodeDirectoryName;
+ }
+
+ /**
+ * Set the name of the directory where the Hds code shall be generated.
+ *
+ * @param codeDirectoryName The code directory
+ */
+ public final void setHdsCodeDirectoryName(String codeDirectoryName) {
+ _hdsCodeDirectoryName = codeDirectoryName;
+ }
+
+ /**
+ * Get the name of the protothread directory.
+ *
+ * @return The directory name of the protohread directory
+ */
+ public final String getProtothreadCodeDirectoryName() {
+ return _protothreadCodeDirectoryName;
+ }
+
+ /**
+ * Set the name of the directory where the protothread code shall be generated.
+ *
+ * @param codeDirectoryName The code directory
+ */
+ public final void setProtothreadCodeDirectoryName(String codeDirectoryName) {
+ _protothreadCodeDirectoryName = codeDirectoryName;
+ }
+
+ /**
+ * Get the name of the CBE directory.
+ *
+ * @return The directory name of the CBE directory
+ */
+ public final String getCbeCodeDirectoryName() {
+ return _cbeCodeDirectoryName;
+ }
+
+ /**
+ * Set the name of the directory where the CBE code shall be generated.
+ *
+ * @param codeDirectoryName The code directory
+ */
+ public final void setCbeCodeDirectoryName(String codeDirectoryName) {
+ _cbeCodeDirectoryName = codeDirectoryName;
+ }
+
+ /**
+ * Get the name of the YAPI directory.
+ *
+ * @return The directory name of the CBE directory
+ */
+ public final String getYapiCodeDirectoryName() {
+ return _yapiCodeDirectoryName;
+ }
+
+ /**
+ * Set the name of the directory where the YAPI code shall be generated.
+ *
+ * @param codeDirectoryName The code directory
+ */
+ public final void setYapiCodeDirectoryName(String codeDirectoryName) {
+ _yapiCodeDirectoryName = codeDirectoryName;
+ }
+
+ /**
+ * Get the name of the RTEMS directory.
+ *
+ * @return The directory name of the RTEMS directory
+ */
+ public final String getRtemsCodeDirectoryName() {
+ return _rtemsCodeDirectoryName;
+ }
+
+ /**
+ * Set the name of the directory where the RTEMS code shall be generated.
+ *
+ * @param codeDirectoryName The code directory
+ */
+ public final void setRtemsCodeDirectoryName(String codeDirectoryName) {
+ _rtemsCodeDirectoryName = codeDirectoryName;
+ }
+
+ /**
+ * Get the name of the RTEMS board support package.
+ *
+ * @return The name of the board support package
+ */
+ public final String getRtemsBSP() {
+ return _rtemsBSP;
+ }
+
+ /**
+ * Set the name of the board support package for which RTEMS code shall
+ * be generated.
+ *
+ * @param bsp board support package for which code is generated
+ * currently supported: pc386, mparm
+ */
+ public final void setRtemsBSP(String bsp) {
+ _rtemsBSP = bsp;
+ }
+
+ /**
+ * Get the status of the Verbose flag.
+ *
+ * @return verbose flag value
+ */
+ public final boolean getVerboseFlag() {
+ return _verbose;
+ }
+
+ /**
+ * Set the Verbose flag.
+ */
+ public final void setVerboseFlag() {
+ _verbose = true;
+ }
+
+ /**
+ * Get the status of the Debug flag.
+ *
+ * @return debug flag value
+ */
+ public final boolean getDebugFlag() {
+ return _debug;
+ }
+
+ /**
+ * Set the debug flag.
+ */
+ public final void setDebugFlag() {
+ _debug = true;
+ }
+
+ /**
+ * Get the status of the SystemC flag
+ *
+ * @return The systemC flag value
+ */
+ public final boolean getSystemCFlag() {
+ return _systemC;
+ }
+
+ /**
+ * Set the SystemC flag.
+ */
+ public final void setSystemCFlag() {
+ _systemC = true;
+ }
+
+ /**
+ * Get the status of the PipeAndFilter flag.
+ *
+ * @return PipeAndFilter flag value
+ */
+ public final boolean getPipeAndFilterFlag() {
+ return _pipeAndFilter;
+ }
+
+ /**
+ * Set the PipeAndFilter flag.
+ */
+ public final void setPipeAndFilterFlag() {
+ _pipeAndFilter = true;
+ }
+
+ /**
+ * Get the status of the protothread flag.
+ *
+ * @return PipeAndFilter flag value
+ */
+ public final boolean getProtothreadFlag() {
+ return _protothread;
+ }
+
+ /**
+ * Set the protothread flag.
+ */
+ public final void setProtothreadFlag() {
+ _protothread = true;
+ }
+
+ /**
+ * Get the status of the HdS flag.
+ *
+ * @return The HdS flag value
+ */
+ public final boolean getHdsFlag() {
+ return _hds;
+ }
+
+ /**
+ * Set the HdS flag.
+ */
+ public final void setHdsFlag() {
+ _hds = true;
+ }
+
+ /**
+ * Get the status of the RTEMS flag.
+ *
+ * @return The HdS flag value
+ */
+ public final boolean getRtemsFlag() {
+ return _rtems;
+ }
+
+ /**
+ * Set the RTEMS flag.
+ */
+ public final void setRtemsFlag() {
+ _rtems = true;
+ }
+
+ /**
+ * Get the status of the CBE flag.
+ *
+ * @return The CBE flag value
+ */
+ public final boolean getCbeFlag() {
+ return _cbe;
+ }
+
+ /**
+ * Set the CBE flag.
+ */
+ public final void setCbeFlag() {
+ _cbe = true;
+ }
+
+ /**
+ * Set the YAPI flag.
+ */
+ public final void setYapiFlag() {
+ _yapi = true;
+ }
+
+ /**
+ * Get the status of the YAPI flag.
+ *
+ * @return The YAPI flag value
+ */
+ public final boolean getYapiFlag() {
+ return _yapi;
+ }
+
+ /**
+ * Get the status of the dotty flag
+ *
+ * @return The dotty Flag value
+ */
+ public final boolean getDottyFlag() {
+ return _dotty;
+ }
+
+ /**
+ * Sets the dotty flag
+ */
+ public final void setDottyFlag() {
+ _dotty = true;
+ }
+
+ /**
+ * Get the status of the profiling flag
+ *
+ * @return The profiling Flag value
+ */
+ public final boolean getProfilingFlag() {
+ return _profiling;
+ }
+
+ /**
+ * Sets the profiling flag
+ */
+ public final void setProfilingFlag() {
+ _profiling = true;
+ }
+
+ /**
+ * Get the status of the vsp log flag.
+ *
+ * @return The vsp log value
+ */
+ public final boolean getVspLogFlag() {
+ return _vsplog;
+ }
+
+ /**
+ * Sets the vsp log flag.
+ */
+ public final void setVspLogFlag() {
+ _vsplog = true;
+ }
+
+ /**
+ * Get the status of the workload annotation flag.
+ *
+ * @return workload flag
+ */
+ public final boolean getWorkloadFlag() {
+ return _workload;
+ }
+
+ /**
+ * Sets the workload flag.
+ */
+ public final void setWorkloadFlag() {
+ _workload = true;
+ }
+
+ /**
+ * Get the status of the xml generation flag
+ *
+ * @return The xmlGen Flag value
+ */
+ public final boolean getXmlGenFlag() {
+ return _xmlGen;
+ }
+
+ /**
+ * Sets the xml generation flag
+ */
+ public final void setXmlGenFlag() {
+ _xmlGen = true;
+ }
+
+ /**
+ * Get the status of the check flag
+ *
+ * @return The check Flag value
+ */
+ public final boolean getCheckFlag() {
+ return _check;
+ }
+
+ /**
+ * Sets the check flag
+ */
+ public final void setCheckFlag() {
+ _check = true;
+ }
+
+ /**
+ * Get the status of the path finder flag
+ *
+ * @return The path finder Flag value
+ */
+ public final boolean getPathsFlag() {
+ return _archiPaths;
+ }
+
+ /**
+ * Sets the check flag
+ */
+ public final void setPathsFlag() {
+ _archiPaths = true;
+ }
+
+ /**
+ * Print a message to screen if the verbose flag has been selected with an
+ * end-of-line.
+ *
+ * @param s description that needs to printed.
+ */
+ public void printVerbose(String s) {
+ if ( getVerboseFlag() ) {
+ System.out.print(s);
+ }
+ }
+
+ /**
+ * Print a message to screen if the verbose flag has been selected.
+ *
+ * @param s description that needs to printed.
+ */
+ public void printlnVerbose(String s) {
+ if( getVerboseFlag() ) {
+ System.out.println(s);
+ }
+ }
+
+
+ /**
+ * get the name of the output file name.
+ *
+ * @return The outputFileName value
+ */
+ public final String getOutputFileName() {
+ return _outputFileName;
+ }
+
+ /**
+ * set the name of the input file name.
+ *
+ * @param filename The new outputFileName value
+ */
+ public final void setOutputFileName(String filename) {
+ _outputFileName = filename;
+ }
+
+ /**
+ * get the base path name.
+ *
+ * @return The basePath value
+ */
+ public final String getBasePath() { return _basePath; }
+
+ /**
+ * sets the base path name.
+ *
+ * @param name
+ * The new basePath value
+ */
+ public final void setBasePath(String name) { _basePath = name; }
+
+ /**
+ * get the trace filename.
+ *
+ * @return The name value of trace file
+ */
+ public final String getTraceName() { return _traceName; }
+
+ /**
+ * sets the trace Filename.
+ *
+ * @param name trace filename
+ */
+ public final void setTraceName(String name) {
+ _traceName = name;
+ }
+
+
+ /**
+ * Get the vsp log filename.
+ *
+ * @return name of the vsp log file
+ */
+ public final String getVspLogFileName() {
+ return _vspLogFileName;
+ }
+
+ /**
+ * Set the vsp log filename.
+ *
+ * @param name vsp log filename
+ */
+ public final void setVspLogFileName(String name) {
+ _vspLogFileName = name;
+ }
+
+ /**
+ * Get the workload filename.
+ *
+ * @return name workload filename
+ */
+ public final String getWorkloadFileName() {
+ return _workloadFileName;
+ }
+
+ /**
+ * Sets the workload filename.
+ *
+ * @param name workload filename
+ */
+ public final void setWorkloadFileName(String name) {
+ _workloadFileName = name;
+ }
+
+ /**
+ * Constructor. Private since only a single version may exist.
+ */
+ private UserInterface() {
+ _rb = ResourceBundle.getBundle(_rbFileName);
+ }
+}
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+DOL main program (commandline handling and dispatching of functions).
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: XmlErrorHandler.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.parser.xml;
+
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * This class ...
+ */
+
+public class XmlErrorHandler extends DefaultHandler {
+
+ /**
+ * Empty constructor
+ */
+ public XmlErrorHandler() {
+ super();
+ }
+
+ /**
+ * Treat validation errors as fatal
+ *
+ * @param e Description of the Parameter
+ * @exception SAXParseException MyException If such and such occurs
+ */
+ public void error(SAXParseException e)
+ throws SAXParseException {
+ System.out.println("Error found: " + e.getMessage());
+ throw e;
+ }
+
+ /**
+ * Dump warnings too
+ *
+ * @param err Description of the Parameter
+ * @exception SAXParseException MyException If such and such occurs
+ */
+ public void warning(SAXParseException err)
+ throws SAXParseException {
+ System.out.println("** Warning"
+ + ", line " + err.getLineNumber()
+ + ", uri " + err.getSystemId());
+ System.out.println(" " + err.getMessage());
+ }
+}
--- /dev/null
+/* $Id: XmlParser.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.parser.xml;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.xerces.parsers.SAXParser;
+import org.xml.sax.SAXException;
+
+import dol.main.UserInterface;
+
+/**
+ * Parser for DOL XML files.
+ */
+public class XmlParser extends org.xml.sax.helpers.DefaultHandler {
+
+ /**
+ * Constructor. Initializes the parser.
+ */
+ public XmlParser() {
+ super();
+ try {
+ _parser = new SAXParser();
+ _parser.setFeature("http://xml.org/sax/features/validation",
+ true);
+ _parser.setFeature("http://apache.org/xml/features/"
+ + "validation/schema", true);
+ _parser.setFeature("http://apache.org/xml/features/"
+ + "validation/schema-full-checking", true);
+ _parser.setErrorHandler(new XmlErrorHandler());
+ _parser.setContentHandler(this);
+ _parser.setProperty("http://apache.org/xml/properties/schema/"
+ + "external-schemaLocation",
+ dol.util.SchemaLocation.getInternalSchemaLocation());
+ _parser.setContentHandler(this);
+ _parser.setErrorHandler(new XmlErrorHandler());
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ /**
+ * Return a absolute URL reference for the given URL.
+ *
+ * @param url url
+ * @return absolute URL reference
+ */
+ protected String _makeAbsoluteURL(String url)
+ throws MalformedURLException {
+ URL baseURL;
+ String fileSep = System.getProperty("file.separator");
+ String base = "";
+
+ // Replace all separators in given URL
+ url = url.replace(fileSep.charAt(0), '/');
+
+ // Add working directory if URL is not absolute
+ if (url.charAt(0) != '/' && !url.matches("^[A-Za-z]:/.*")) {
+ base = System.getProperty("user.dir") + '/';
+ base = base.replace(fileSep.charAt(0), '/');
+ if (base.charAt(0) != '/') {
+ base = "/" + base;
+ }
+ }
+
+ // Add front slash to Windows style URLs
+ if (url.matches("^[A-Za-z]:/.*")) {
+ url = "/" + url;
+ }
+
+ baseURL = new URL("file", null, base);
+ System.out.println(" -- full filename: "
+ + new URL(baseURL, url).toString());
+ return new URL(baseURL, url).toString();
+ }
+
+ /** XML parser */
+ protected SAXParser _parser;
+
+ /** user interface used for messages for users */
+ protected UserInterface _ui = UserInterface.getInstance();
+}
--- /dev/null
+/* $Id: ArchiXmlParser.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.parser.xml.archischema;\r
+\r
+import java.util.Stack;\r
+\r
+import org.xml.sax.Attributes;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.SAXParseException;\r
+\r
+import dol.datamodel.XmlTag;\r
+import dol.datamodel.architecture.Architecture;\r
+import dol.parser.xml.XmlParser;\r
+\r
+/**\r
+ * Parse architecture XML file.\r
+ */\r
+public class ArchiXmlParser extends XmlParser {\r
+\r
+ /**\r
+ * Constructor.\r
+ */\r
+ public ArchiXmlParser() {\r
+ super();\r
+ _stack = new Stack<Object>();\r
+ _xml2Archi = new Xml2Archi();\r
+ }\r
+\r
+ /**\r
+ * Do the parsing of an XML file describing an architecture.\r
+ *\r
+ * @param url The input XML file\r
+ * @return the architecture\r
+ */\r
+ public Architecture doParse(String url) {\r
+ Architecture architecture = null;\r
+ System.out.println("Read architecture from XML file");\r
+\r
+ try {\r
+ String uri = _makeAbsoluteURL(url);\r
+ _ui.printlnVerbose("-- processing XML file: " + uri);\r
+ _ui.printlnVerbose("-- read XML file: ");\r
+ _stack.clear();\r
+ _parser.parse(new InputSource(uri));\r
+ architecture = (Architecture) _stack.pop();\r
+ _ui.printlnVerbose(" [DONE] ");\r
+ } catch (SAXParseException err) {\r
+ System.out.println("** Parsing error, line "\r
+ + err.getLineNumber() + ", uri " + err.getSystemId());\r
+ System.out.println(" " + err.getMessage());\r
+ } catch (SAXException e) {\r
+ e.printStackTrace();\r
+ } catch (Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+\r
+ architecture.computePaths();\r
+\r
+ System.out.println(" -- Architecture model from XML "\r
+ + "[Finished]");\r
+ System.out.println();\r
+\r
+ return architecture;\r
+ }\r
+\r
+ /**\r
+ * Action to be done while parsing a start element of an XML.\r
+ *\r
+ * @param elementName Description of the Parameter\r
+ * @param attributes Description of the Parameter\r
+ * @exception SAXException MyException If such and such occurs\r
+ */\r
+ public void startElement(String namespaceURI, String localName,\r
+ String elementName, Attributes attributes)\r
+ throws SAXException {\r
+ Object val = null;\r
+\r
+ if (elementName.equals(_xt.getArchiTag())) {\r
+ val = _xml2Archi.processArchitecture(attributes);\r
+ } else if (elementName.equals(_xt.getVariableTag())) {\r
+ val = _xml2Archi.processVariable(attributes);\r
+ } else if (elementName.equals(_xt.getProcessorTag())) {\r
+ val = _xml2Archi.processProcessor(attributes);\r
+ } else if (elementName.equals(_xt.getMemoryTag())) {\r
+ val = _xml2Archi.processMemory(attributes);\r
+ } else if (elementName.equals(_xt.getHWChannelTag())) {\r
+ val = _xml2Archi.processHWChannel(attributes);\r
+ } else if (elementName.equals(_xt.getConfigurationTag())) {\r
+ val = _xml2Archi.processConfiguration(attributes);\r
+ // simplified architecture\r
+ } else if (elementName.equals(_xt.getConnectionTag())) {\r
+ val = _xml2Archi.processConnection(attributes);\r
+ } else if (elementName.equals(_xt.getOriginTag())) {\r
+ val = _xml2Archi.processOrigin(attributes);\r
+ } else if (elementName.equals(_xt.getTargetTag())) {\r
+ val = _xml2Archi.processTarget(attributes);\r
+ } else if (elementName.equals(_xt.getNodeTag())) {\r
+ val = _xml2Archi.processNode(attributes);\r
+ } else if (elementName.equals(_xt.getPortTag())) {\r
+ val = _xml2Archi.processPort(attributes);\r
+ } else if (elementName.equals(_xt.getInPortTag())) {\r
+ val = _xml2Archi.processInputPort(attributes);\r
+ } else if (elementName.equals(_xt.getOutPortTag())) {\r
+ val = _xml2Archi.processOutputPort(attributes);\r
+ } else if (elementName.equals(_xt.getDuplexPortTag())) {\r
+ val = _xml2Archi.processInOutPort(attributes);\r
+ // detailed architecture\r
+ } else if (elementName.equals(_xt.getReadPathTag())) {\r
+ val = _xml2Archi.processReadPath(attributes);\r
+ } else if (elementName.equals(_xt.getWritePathTag())) {\r
+ val = _xml2Archi.processWritePath(attributes);\r
+ } else if (elementName.equals(_xt.getTXBufTag())) {\r
+ val = _xml2Archi.processTXBuf(attributes);\r
+ } else if (elementName.equals(_xt.getRXBufTag())) {\r
+ val = _xml2Archi.processRXBuf(attributes);\r
+ } else if (elementName.equals(_xt.getCHBufTag())) {\r
+ val = _xml2Archi.processCHBuf(attributes);\r
+ } else {\r
+ System.out.println("--Warning, DOL doesn't "\r
+ + "understand tag <" + elementName + "> ");\r
+ }\r
+\r
+ if (val != null) {\r
+ _stack.push(val);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Action to be done while parsing an end element of an XML.\r
+ *\r
+ * @param elementName Description of the Parameter\r
+ * @exception SAXException MyException If such and such occurs\r
+ */\r
+ public void endElement(String namespaceURI, String localName,\r
+ String elementName) throws SAXException {\r
+ if (elementName.equals(_xt.getArchiTag())) {\r
+ _xml2Archi.processArchitecture(_stack);\r
+ } else if (elementName.equals(_xt.getVariableTag())) {\r
+ _xml2Archi.processVariable(_stack);\r
+ } else if (elementName.equals(_xt.getProcessorTag())) {\r
+ _xml2Archi.processProcessor(_stack);\r
+ } else if (elementName.equals(_xt.getMemoryTag())) {\r
+ _xml2Archi.processMemory(_stack);\r
+ } else if (elementName.equals(_xt.getHWChannelTag())) {\r
+ _xml2Archi.processHWChannel(_stack);\r
+ } else if (elementName.equals(_xt.getConfigurationTag())) {\r
+ _xml2Archi.processConfiguration(_stack);\r
+ // simplified architecture\r
+ } else if (elementName.equals(_xt.getConnectionTag())) {\r
+ _xml2Archi.processConnection(_stack);\r
+ } else if (elementName.equals(_xt.getOriginTag())) {\r
+ _xml2Archi.processOrigin(_stack);\r
+ } else if (elementName.equals(_xt.getTargetTag())) {\r
+ _xml2Archi.processTarget(_stack);\r
+ } else if (elementName.equals(_xt.getNodeTag())) {\r
+ _xml2Archi.processNode(_stack);\r
+ } else if (elementName.equals(_xt.getPortTag())) {\r
+ _xml2Archi.processPort(_stack);\r
+ } else if (elementName.equals(_xt.getInPortTag())) {\r
+ _xml2Archi.processInputPort(_stack);\r
+ } else if (elementName.equals(_xt.getOutPortTag())) {\r
+ _xml2Archi.processOutputPort(_stack);\r
+ } else if (elementName.equals(_xt.getDuplexPortTag())) {\r
+ _xml2Archi.processInOutPort(_stack);\r
+ // detailed architecture\r
+ } else if (elementName.equals(_xt.getReadPathTag())) {\r
+ _xml2Archi.processReadPath(_stack);\r
+ } else if (elementName.equals(_xt.getWritePathTag())) {\r
+ _xml2Archi.processWritePath(_stack);\r
+ } else if (elementName.equals(_xt.getTXBufTag())) {\r
+ _xml2Archi.processTXBuf(_stack);\r
+ } else if (elementName.equals(_xt.getRXBufTag())) {\r
+ _xml2Archi.processRXBuf(_stack);\r
+ } else if (elementName.equals(_xt.getCHBufTag())) {\r
+ _xml2Archi.processCHBuf(_stack);\r
+ }\r
+ }\r
+\r
+ /** stack containing the generated objects */\r
+ protected Stack<Object> _stack;\r
+\r
+ /** actions to be taken while parsing every XML element */\r
+ protected Xml2Archi _xml2Archi;\r
+\r
+ /** */\r
+ protected XmlTag _xt = XmlTag.getInstance();\r
+}\r
--- /dev/null
+/* $Id: Xml2Archi.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.parser.xml.archischema;
+
+import java.util.Stack;
+
+import org.xml.sax.Attributes;
+
+import dol.datamodel.architecture.ArchiConnection;
+import dol.datamodel.architecture.ArchiResource;
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.architecture.Configuration;
+import dol.datamodel.architecture.HWChannel;
+import dol.datamodel.architecture.Memory;
+import dol.datamodel.architecture.Node;
+import dol.datamodel.architecture.PortNode;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.architecture.ReadPath;
+import dol.datamodel.architecture.Variable;
+import dol.datamodel.architecture.WritePath;
+
+/**
+ * Parse architecture XML file.
+ */
+public class Xml2Archi {
+
+ /**
+ * Constructor.
+ */
+ public Xml2Archi() {
+ }
+
+ /**
+ * Process the start of the Architecture tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return an Architecture object
+ */
+ public Architecture processArchitecture(Attributes attributes) {
+ Architecture arch = new Architecture(attributes.getValue("name"));
+ return arch;
+
+ }
+
+ /**
+ * Process the end of the Architecture tag in the XML.
+ *
+ * @param stack
+ */
+ public void processArchitecture(Stack<Object> stack) {
+ }
+
+ /**
+ * Process the start of a processor tag in the XML.
+ *
+ * @param attributes The attributes of the tag.
+ * @return a processor object.
+ */
+ public Processor processProcessor(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+ String type = (String) attributes.getValue("type");
+ Processor processor = new Processor(name);
+ if (basename != null) processor.setBasename(basename);
+ if (range != null) processor.setRange(range);
+ if (type != null) processor.setType(type);
+ return processor;
+ }
+
+ /**
+ * Process the end of a processor tag in the XML.
+ *
+ * @param stack
+ */
+ public void processProcessor(Stack<Object> stack) {
+ Processor p = (Processor) stack.pop();
+
+ if (stack.peek() instanceof ReadPath) {
+ ReadPath r = (ReadPath) stack.peek();
+ Processor pro = ((Architecture)stack.elementAt(0)).
+ getProcessor(p.getName());
+ if (pro != null) {
+ r.setProcessor(pro);
+ }
+ else {
+ undefinedReference("ReadPath", r.getName(),
+ "processor", p.getName());
+ }
+ } else if (stack.peek() instanceof WritePath) {
+ WritePath w = (WritePath) stack.peek();
+ Processor pro = ((Architecture)stack.elementAt(0)).
+ getProcessor(p.getName());
+ if (pro != null) {
+ w.setProcessor(pro);
+ }
+ else {
+ undefinedReference("ReadPath", w.getName(),
+ "processor", p.getName());
+ }
+ } else if (stack.peek() instanceof Architecture) {
+ Architecture a = (Architecture)stack.peek();
+ p.setParentResource(a);
+ a.getProcessorList().add(p);
+ }
+ }
+
+ /**
+ * Process the start of a memory tag in the XML.
+ *
+ * @param attributes The attributes of the tag.
+ * @return a memory object.
+ */
+ public Memory processMemory(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+ String type = (String) attributes.getValue("type");
+ Memory memory = new Memory(name);
+ if (basename != null) memory.setBasename(basename);
+ if (range != null) memory.setRange(range);
+ if (type != null) memory.setRange(type);
+ return memory;
+ }
+
+ /**
+ * Process the end of a memory tag in the XML.
+ *
+ * @param stack
+ */
+ public void processMemory(Stack<Object> stack) {
+ Memory m = (Memory) stack.pop();
+ Architecture a = (Architecture)stack.peek();
+ a.getMemoryList().add(m);
+ m.setParentResource(a);
+ }
+
+ /**
+ * Process the start of a hw_channel tag in the XML.
+ *
+ * @param attributes The attributes of the tag.
+ * @return a hw_chnannel object.
+ */
+ public HWChannel processHWChannel(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+ String type = (String) attributes.getValue("type");
+ HWChannel hw_channel = new HWChannel(name);
+ if (basename != null) hw_channel.setBasename(basename);
+ if (range != null) hw_channel.setRange(range);
+ if (type != null) hw_channel.setType(type);
+ return hw_channel;
+ }
+
+ /**
+ * Process the end of an hw_channel tag in the XML.
+ *
+ * @param stack
+ */
+ public void processHWChannel(Stack<Object> stack) {
+ HWChannel c = (HWChannel) stack.pop();
+ if (stack.peek() instanceof Architecture) {
+ Architecture a = (Architecture)stack.peek();
+ a.getHWChannelList().add(c);
+ c.setParentResource(a);
+ } else if (stack.peek() instanceof WritePath) {
+ WritePath w = (WritePath)stack.peek();
+ HWChannel ch = ((Architecture)stack.elementAt(0)).
+ getHWChannel(c.getName());
+ if (ch != null) {
+ w.getHWChannelList().add(ch);
+ }
+ else {
+ undefinedReference("WritePath", w.getName(),
+ "hwchannel", c.getName());
+ }
+ } else if (stack.peek() instanceof ReadPath) {
+ ReadPath r = (ReadPath)stack.peek();
+ HWChannel ch = ((Architecture)stack.elementAt(0)).
+ getHWChannel(c.getName());
+ if (ch != null) {
+ r.getHWChannelList().add(ch);
+ }
+ else {
+ undefinedReference("ReadPath", r.getName(),
+ "hwchannel", c.getName());
+ }
+ }
+ }
+
+ /**
+ * Process the start of a node tag in the XML.
+ *
+ * @param attributes The attributes of the tag.
+ * @return a node object.
+ */
+ public Node processNode(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+ Node node = new Node(name);
+ if (basename != null) node.setBasename(basename);
+ if (range != null) node.setRange(range);
+ return node;
+ }
+
+ /**
+ * Process the end of an node tag in the XML.
+ *
+ * @param stack
+ */
+ public void processNode(Stack<Object> stack) {
+ Node n = (Node) stack.pop();
+ ArchiResource r = (ArchiResource)stack.peek();
+ r.getNodeList().add(n);
+ }
+
+ /**
+ * Process the start of a origin tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a ArchiResource object
+ */
+ public ArchiResource processOrigin(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ ArchiResource resource = new ArchiResource(name);
+ if (basename != null) resource.setBasename(basename);
+
+ return resource;
+ }
+
+ /**
+ * Process the end of a origin tag in the XML.
+ *
+ * @param stack
+ */
+ public void processOrigin(Stack<Object> stack) {
+ ArchiResource resource = (ArchiResource) stack.pop();
+ ArchiConnection connection = (ArchiConnection) stack.peek();
+ connection.setOrigin(resource);
+ }
+
+ /**
+ * Process the start of a target tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a ArchiResource object
+ */
+ public ArchiResource processTarget(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ ArchiResource resource = new ArchiResource(name);
+ if (basename != null) resource.setBasename(basename);
+
+ return resource;
+ }
+
+ /**
+ * Process the end of a target tag in the XML.
+ *
+ * @param stack
+ */
+ public void processTarget(Stack<Object> stack) {
+ ArchiResource resource = (ArchiResource) stack.pop();
+ ArchiConnection connection = (ArchiConnection) stack.peek();
+ connection.setTarget(resource);
+ }
+
+ /**
+ * Process the start of a connection tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a ArchiConnection object
+ */
+ public ArchiConnection processConnection(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ ArchiConnection connection = new ArchiConnection(name);
+ if (basename != null) connection.setBasename(basename);
+
+ return connection;
+ }
+
+ /**
+ * Process the end of a connection tag in the XML.
+ *
+ * @param stack
+ */
+ public void processConnection(Stack<Object> stack) {
+ ArchiConnection connection = (ArchiConnection) stack.pop();
+ Architecture architecture = (Architecture)stack.peek();
+ architecture.getConnectionList().add(connection);
+ connection.setParentResource(architecture);
+ }
+
+ /**
+ * Process the start of an inputport/outputport/port tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a PortNode object
+ */
+ public PortNode processInputPort(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+
+ PortNode port = new PortNode(name, PortNode.INPORT);
+
+ if (basename != null)
+ port.setBasename(basename);
+ else
+ port.setBasename(name);
+
+ if (range != null)
+ port.setRange(range);
+
+ return port;
+ }
+
+ public PortNode processOutputPort(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+
+ PortNode port = new PortNode(name, PortNode.OUTPORT);
+
+ if (basename != null)
+ port.setBasename(basename);
+ else
+ port.setBasename(name);
+
+ if (range != null)
+ port.setRange(range);
+
+ return port;
+ }
+
+ // duplexport
+ public PortNode processInOutPort(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+
+ PortNode port = new PortNode(name, PortNode.INOUTPORT);
+
+ if (basename != null)
+ port.setBasename(basename);
+ else
+ port.setBasename(name);
+
+ if (range != null)
+ port.setRange(range);
+
+ return port;
+ }
+
+ public PortNode processPort(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+
+ PortNode port = new PortNode(name);
+
+ if (basename != null)
+ port.setBasename(basename);
+ else
+ port.setBasename(name);
+
+ if (range != null)
+ port.setRange(range);
+
+ return port;
+ }
+
+ /**
+ * Process the end of an inputport/outputport/duplexport/port tag in the XML.
+ *
+ * @param stack
+ */
+ public void processInputPort(Stack<Object> stack) {
+ PortNode port = (PortNode) stack.pop();
+ Node node = (Node) stack.peek();
+ port.setNode(node);
+ node.getPortList().add(port);
+ }
+
+ public void processOutputPort(Stack<Object> stack) {
+ PortNode port = (PortNode) stack.pop();
+ Node node = (Node) stack.peek();
+ port.setNode(node);
+ node.getPortList().add(port);
+ }
+
+ public void processInOutPort(Stack<Object> stack) {
+ PortNode port = (PortNode) stack.pop();
+ Node node = (Node) stack.peek();
+ port.setNode(node);
+ node.getPortList().add(port);
+ }
+
+ public void processPort(Stack<Object> stack) {
+ PortNode port = (PortNode) stack.pop();
+ Node node = (Node) stack.peek();
+ port.setNode(node);
+ node.getPortList().add(port);
+ }
+
+ /**
+ * Process the start of a variable tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Variable object
+ */
+ public Variable processVariable(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String value = (String) attributes.getValue("value");
+ Variable variable = null;
+ variable = new Variable(name);
+ variable.setValue(Integer.parseInt(value));
+
+ return variable;
+ }
+
+ /**
+ * Process the end of a variable tag in the XML.
+ *
+ * @param stack
+ */
+ public void processVariable(Stack<Object> stack) {
+ Variable variable = (Variable) stack.pop();
+ Architecture architecture = (Architecture)stack.peek();
+ variable.setParentResource(architecture);
+ architecture.getVarList().add(variable);
+ }
+
+ /**
+ * Process the start of a configuration tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Configuration object
+ */
+ public Configuration processConfiguration(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String value = (String) attributes.getValue("value");
+ Configuration config = new Configuration(name);
+ config.setValue(value);
+ return config;
+ }
+
+ /**
+ * Process the end of a configuration tag in the XML.
+ *
+ * @param stack
+ */
+ public void processConfiguration(Stack<Object> stack) {
+ Configuration config = (Configuration) stack.pop();
+ ArchiResource res = (ArchiResource)stack.peek();
+ res.getCfgList().add(config);
+ }
+
+ /**
+ * Process the start of a readPath tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a ReadPath object
+ */
+ public ReadPath processReadPath(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ ReadPath readpath = new ReadPath(name);
+ return readpath;
+ }
+
+ /**
+ * Process the end of a readpath tag in the XML.
+ *
+ * @param stack
+ */
+ public void processReadPath(Stack<Object> stack) {
+ ReadPath readpath = (ReadPath) stack.pop();
+ Architecture res = (Architecture)stack.peek();
+ res.getReadPathList().add(readpath);
+ }
+
+ /**
+ * Process the start of a WritePath tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a WritePath object
+ */
+ public WritePath processWritePath(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ WritePath writepath = new WritePath(name);
+ return writepath;
+ }
+
+ /**
+ * Process the end of a WritePath tag in the XML.
+ *
+ * @param stack
+ */
+ public void processWritePath(Stack<Object> stack) {
+ WritePath writepath = (WritePath) stack.pop();
+ Architecture res = (Architecture)stack.peek();
+ res.getWritePathList().add(writepath);
+ }
+
+ /**
+ * Process the start of a TXBuf tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a TXBuf object
+ */
+ public String processTXBuf(Attributes attributes) {
+ return attributes.getValue("name");
+ }
+
+ /**
+ * Process the end of a TXBuf tag in the XML.
+ *
+ * @param stack
+ */
+ public void processTXBuf(Stack<Object> stack) {
+ String txBuf = (String) stack.pop();
+ WritePath res = (WritePath)stack.peek();
+ Memory mem = ((Architecture)res.getProcessor().getParentResource()).getMemory(txBuf);
+ if (mem != null) {
+ res.setTXBuf(mem);
+ }
+ else {
+ undefinedReference("ReadPath", res.getName(),
+ "transmit buffer", txBuf);
+ }
+ }
+
+ /**
+ * Process the start of a RXBuf tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a RXBuf object
+ */
+ public String processRXBuf(Attributes attributes) {
+ return attributes.getValue("name");
+ }
+
+ /**
+ * Process the end of a RXBuf tag in the XML.
+ *
+ * @param stack
+ */
+ public void processRXBuf(Stack<Object> stack) {
+ String rxBuf = (String) stack.pop();
+ ReadPath res = (ReadPath)stack.peek();
+ Memory mem = ((Architecture)res.getProcessor().getParentResource()).getMemory(rxBuf);
+ if (mem != null) {
+ res.setRXBuf(mem);
+ }
+ else {
+ undefinedReference("ReadPath", res.getName(),
+ "receive buffer", rxBuf);
+ }
+ }
+
+ /**
+ * Process the start of a CHBuf tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a CHBuf object
+ */
+ public String processCHBuf(Attributes attributes) {
+ return attributes.getValue("name");
+ }
+
+ /**
+ * Process the end of a CHBuf tag in the XML.
+ *
+ * @param stack
+ */
+ public void processCHBuf(Stack<Object> stack) {
+ String value= (String) stack.pop();
+ if (stack.peek() instanceof ReadPath) {
+ ReadPath res = (ReadPath)stack.peek();
+ Memory mem = ((Architecture)res.getProcessor().
+ getParentResource()).getMemory(value);
+ if (mem != null) {
+ res.setCHBuf(mem);
+ }
+ else {
+ undefinedReference("ReadPath", res.getName(),
+ "channel buffer", value);
+ }
+ }
+ else if (stack.peek() instanceof WritePath) {
+ WritePath res = (WritePath)stack.peek();
+ Memory mem = ((Architecture)res.getProcessor().
+ getParentResource()).getMemory(value);
+ if (mem != null) {
+ res.setCHBuf(mem);
+ }
+ else {
+ undefinedReference("WritePath", res.getName(),
+ "channel buffer", value);
+ }
+ }
+ }
+
+
+ /**
+ * Write an error message and terminate program in case an
+ * architecture element is referenced which does not exist.
+ *
+ * @param elementType type of architecture element in which the error
+ * occurred
+ * @param elementName name of architecture element in which the error
+ * occurred
+ * @param referenceType type of referenced architecture element
+ * @param referenceName name of referenced architecture element
+ */
+ protected void undefinedReference(String elementType,
+ String elementName,
+ String referenceType,
+ String referenceName) {
+ System.out.println("Error: " + elementType + " " + elementName
+ + " references " + referenceType + " " + referenceName
+ + " that has not been declared.");
+ System.out.println("Exit.");
+ System.exit(-1);
+ }
+
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Architecture XML schema parser.
+This package parses the architecture XML and stores the result in internal architectural data model.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: MapXmlParser.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.parser.xml.mapschema;
+
+import java.util.Stack;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import dol.datamodel.XmlTag;
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.parser.xml.XmlParser;
+
+
+/**
+ * Parse mapping XML file.
+ */
+public class MapXmlParser extends XmlParser {
+
+ /**
+ * Constructor.
+ * @param pn the process network the mapping is referring to
+ * @param arch the architecture the mapping is referring to
+ */
+ public MapXmlParser(ProcessNetwork pn, Architecture arch) {
+ super();
+ _stack = new Stack<Object>();
+ _xml2Map = new Xml2Map(pn, arch);
+ }
+
+ /**
+ * Do the parsing of an XML file describing a mapping.
+ *
+ * @param url The input XML file
+ * @return the mapping
+ */
+ public Mapping doParse(String url) {
+ Mapping map = null;
+ System.out.println("Read mapping from XML file");
+
+ try {
+ String uri = _makeAbsoluteURL(url);
+ _ui.printlnVerbose("-- processing XML file: " + uri);
+ _ui.printlnVerbose("-- read XML file: ");
+ _stack.clear();
+ _parser.parse(new InputSource(uri));
+ map = (Mapping) _stack.pop();
+ _ui.printlnVerbose(" [DONE] ");
+ } catch (SAXParseException err) {
+ System.out.println("** Parsing error, line "
+ + err.getLineNumber() + ", uri " + err.getSystemId());
+ System.out.println(" " + err.getMessage());
+ } catch (SAXException e) {
+ //e.printStackTrace();
+ e.getMessage();
+ System.exit(-1);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+
+ System.out.println(" -- Mapping from XML "
+ + "[Finished]");
+ System.out.println();
+
+ return map;
+ }
+
+ /**
+ * Action to be done while parsing a start element of an XML.
+ *
+ * @param elementName Description of the Parameter
+ * @param attributes Description of the Parameter
+ * @exception SAXException MyException If such and such occurs
+ */
+ public void startElement(String namespaceURI, String localName,
+ String elementName, Attributes attributes)
+ throws SAXException {
+ Object val = null;
+
+ if (elementName.equals(_xt.getMappingTag())) {
+ val = _xml2Map.processMapping(attributes);
+ } else if (elementName.equals(_xt.getVariableTag())) {
+ val = _xml2Map.processVariable(attributes);
+ } else if (elementName.equals(_xt.getBindingTag())) {
+ val = _xml2Map.processBinding(attributes);
+ } else if (elementName.equals(_xt.getOriginTag())) {
+ val = _xml2Map.processOrigin(attributes);
+ } else if (elementName.equals(_xt.getProcessTag())) {
+ val = _xml2Map.processProcess(attributes);
+ } else if (elementName.equals(_xt.getProcessorTag())) {
+ val = _xml2Map.processProcessor(attributes);
+ } else if (elementName.equals(_xt.getSWChannelTag())) {
+ val = _xml2Map.processChannel(attributes);
+ } else if (elementName.equals(_xt.getReadPathTag())) {
+ val = _xml2Map.processReadPath(attributes);
+ } else if (elementName.equals(_xt.getWritePathTag())) {
+ val = _xml2Map.processWritePath(attributes);
+ } else if (elementName.equals(_xt.getScheduleTag())) {
+ val = _xml2Map.processSchedule(attributes);
+ } else if (elementName.equals(_xt.getResourceTag())) {
+ val = _xml2Map.processResource(attributes);
+ } else if (elementName.equals(_xt.getConfigurationTag())) {
+ val = _xml2Map.processConfiguration(attributes);
+ } else {
+ System.out.println(" -- Warning, DOL doesn't "
+ + "understand tag <" + elementName + "> ");
+ }
+
+ if (val != null) {
+ _stack.push(val);
+ }
+
+ consistencyCheck(elementName, attributes, val);
+ }
+
+
+ /**
+ * Action to be done while parsing an end element of an XML.
+ *
+ * @param elementName Description of the Parameter
+ * @exception SAXException MyException If such and such occurs
+ */
+ public void endElement(String namespaceURI, String localName,
+ String elementName) throws SAXException {
+ if (elementName.equals(_xt.getMappingTag())) {
+ _xml2Map.processMapping(_stack);
+ } else if (elementName.equals(_xt.getVariableTag())) {
+ _xml2Map.processVariable(_stack);
+ } else if (elementName.equals(_xt.getBindingTag())) {
+ _xml2Map.processBinding(_stack);
+ } else if (elementName.equals(_xt.getOriginTag())) {
+ _xml2Map.processOrigin(_stack);
+ /*
+ } else if (elementName.equals(_xt.getTargetTag())) {
+ _xml2Map.processTarget(_stack);
+ */
+ } else if (elementName.equals(_xt.getProcessTag())) {
+ _xml2Map.processProcess(_stack);
+ } else if (elementName.equals(_xt.getProcessorTag())) {
+ _xml2Map.processProcessor(_stack);
+ } else if (elementName.equals(_xt.getSWChannelTag())) {
+ _xml2Map.processChannel(_stack);
+ } else if (elementName.equals(_xt.getReadPathTag())) {
+ _xml2Map.processReadPath(_stack);
+ } else if (elementName.equals(_xt.getWritePathTag())) {
+ _xml2Map.processWritePath(_stack);
+ } else if (elementName.equals(_xt.getScheduleTag())) {
+ _xml2Map.processSchedule(_stack);
+ } else if (elementName.equals(_xt.getResourceTag())) {
+ _xml2Map.processResource(_stack);
+ } else if (elementName.equals(_xt.getConfigurationTag())) {
+ _xml2Map.processConfiguration(_stack);
+ }
+ }
+
+ /**
+ *
+ */
+ protected void consistencyCheck(String elementName,
+ Attributes attributes, Object val) {
+ boolean isConsistent = true;
+
+ if (elementName.equals(_xt.getProcessorTag())
+ && val == null) {
+ System.out.println(" -- Error: Could not find processor \""
+ + attributes.getValue("name") + "\" in "
+ + "architecture.");
+ isConsistent = false;
+ } else if (elementName.equals(_xt.getProcessTag())
+ && val == null) {
+ System.out.println(" -- Error: Could not find process \""
+ + attributes.getValue("name") + "\" in "
+ + "process network.");
+ isConsistent = false;
+ } else if (elementName.equals(_xt.getSWChannelTag())
+ && val == null) {
+ System.out.println(" -- Error: Could not find channel \""
+ + attributes.getValue("name") + "\" in "
+ + "process network.");
+ isConsistent = false;
+ } else if (elementName.equals(_xt.getReadPathTag())
+ && val == null) {
+ System.out.println(" -- Error: Could not find read path \""
+ + attributes.getValue("name") + "\" in "
+ + "architecture.");
+ isConsistent = false;
+ } else if (elementName.equals(_xt.getWritePathTag())
+ && val == null) {
+ System.out.println(" -- Error: Could not find write path \""
+ + attributes.getValue("name") + "\" in "
+ + "architecture.");
+ isConsistent = false;
+ }
+
+ if (!isConsistent) {
+ System.exit(-1);
+ }
+ }
+
+ /** stack containing the generated objects */
+ protected Stack<Object> _stack;
+
+ /** actions to be taken while parsing every XML element */
+ protected Xml2Map _xml2Map;
+
+ /** */
+ protected XmlTag _xt = XmlTag.getInstance();
+}
--- /dev/null
+package dol.parser.xml.mapschema;
+
+import java.util.Stack;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import dol.datamodel.architecture.ArchiResource;
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.architecture.ReadPath;
+import dol.datamodel.architecture.WritePath;
+import dol.datamodel.mapping.Binding;
+import dol.datamodel.mapping.CommunicationBinding;
+import dol.datamodel.mapping.ComputationBinding;
+import dol.datamodel.mapping.Configuration;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.mapping.Schedule;
+import dol.datamodel.mapping.ScheduleEntry;
+import dol.datamodel.mapping.SchedulingPolicy;
+import dol.datamodel.mapping.Variable;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+
+
+/**
+ *
+ */
+public class Xml2Map {
+
+ /**
+ * Constructor.
+ * @param pn the process network the mapping is refering to
+ * @param arch the architecture the mapping is refering to
+ */
+ public Xml2Map(ProcessNetwork pn, Architecture arch) {
+ _pn = pn;
+ _arch = arch;
+ }
+
+ /**
+ * Process the start of the mapping tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Mapping object
+ */
+ public Mapping processMapping(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ Mapping map = new Mapping(name);
+ map.setArch(_arch);
+ map.setPN(_pn);
+ return map;
+ }
+
+ /**
+ * Process the end of the mapping tag in the XML.
+ *
+ * @param stack
+ */
+ public void processMapping(Stack<Object> stack) {
+ }
+
+ /**
+ * Process the start of a binding tag in the XML.
+ *
+ * @param attributes The attributes of the tag.
+ * @return a Binding object.
+ */
+ public Binding processBinding(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String type = (String) attributes.getValue(
+ "http://www.w3.org/2001/XMLSchema-instance", "type");
+ Binding b = null;
+ // Create ComputationBinding or CommunicationBinding object
+ if(type.equals(Binding.COMPUTATION)) {
+ b = new ComputationBinding(name);
+ } else if(type.equals(Binding.COMMUNICATION)) {
+ b = new CommunicationBinding(name);
+ }
+
+ if (basename != null) b.setBasename(basename);
+
+ return b;
+ }
+
+ /**
+ * Process the end of a binding tag in the XML.
+ *
+ * @param stack
+ */
+ public void processBinding(Stack<Object> stack) throws SAXException
+ {
+ Binding bind = (Binding)stack.pop();
+ Mapping map = (Mapping)stack.peek();
+ bind.setParentResource(map);
+
+ if(bind instanceof ComputationBinding) {
+ ComputationBinding cb = (ComputationBinding)bind;
+ Process process = cb.getProcess();
+ Processor processor = cb.getProcessor();
+ process.setProcessor(processor);
+ processor.getProcessList().add(process);
+
+ map.getCompBindList().add(cb);
+ map.getProcessList().add(process);
+ if (!map.getProcessorList().contains(processor)) {
+ map.getProcessorList().add(processor);
+ }
+
+ } else {
+ map.getCommBindList().add((CommunicationBinding)bind);
+ }
+ }
+
+ /**
+ * Process the start of a origin tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a ScheduleEntry object
+ */
+ public ScheduleEntry processOrigin(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ ScheduleEntry schedEntry = new ScheduleEntry(name);
+
+ // A scheduled resource is either a PN process
+ // or a SW channel.
+ Process process = _pn.getProcess(name);
+ if(process != null) {
+ schedEntry.setConsumer(process);
+ } else {
+ Channel channel = _pn.getChannel(name);
+ schedEntry.setConsumer(channel);
+ }
+ return schedEntry;
+ }
+
+ /**
+ * Process the end of a origin tag in the XML.
+ *
+ * @param stack
+ */
+ public void processOrigin(Stack<Object> stack) {
+ ScheduleEntry schedProcess = (ScheduleEntry) stack.pop();
+ Schedule sched = (Schedule) stack.peek();
+ sched.getEntryList().add(schedProcess);
+ schedProcess.setParentResource(sched);
+ }
+
+ /**
+ * Process the start of a variable tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Variable object
+ */
+ public Variable processVariable(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String value = (String) attributes.getValue("value");
+ Variable variable = new Variable(name);
+ variable.setValue(Integer.parseInt(value));
+ return variable;
+ }
+
+ /**
+ * Process the end of a variable tag in the XML.
+ *
+ * @param stack
+ */
+ public void processVariable(Stack<Object> stack) {
+ Variable variable = (Variable) stack.pop();
+ Mapping map = (Mapping) stack.peek();
+ variable.setParentResource(map);
+ map.getVarList().add(variable);
+ }
+
+ /**
+ * Process the start of a process tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Process object
+ */
+ public Process processProcess(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ Process process = _pn.getProcess(name);
+ return process;
+ }
+
+ /**
+ * Process the end of a process tag in the XML.
+ *
+ * @param stack
+ */
+ public void processProcess(Stack<Object> stack) {
+ Process p = (Process) stack.pop();
+ ComputationBinding b = (ComputationBinding) stack.peek();
+ b.setProcess(p);
+ }
+
+ /**
+ * Process the start of a processor tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Processor object
+ */
+ public Processor processProcessor(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ Processor processor = _arch.getProcessor(name);
+ return processor;
+ }
+
+ /**
+ * Process the end of a processor tag in the XML.
+ *
+ * @param stack
+ */
+ public void processProcessor(Stack<Object> stack) {
+ Processor p = (Processor) stack.pop();
+ ComputationBinding b = (ComputationBinding) stack.peek();
+ b.setProcessor(p);
+ }
+
+ /**
+ * Process the start of a channel tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Channel object
+ */
+ public Channel processChannel(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ Channel channel = _pn.getChannel(name);
+ return channel;
+ }
+
+ /**
+ * Process the end of a channel tag in the XML.
+ *
+ * @param stack
+ */
+ public void processChannel(Stack<Object> stack) {
+ Channel chan = (Channel) stack.pop();
+ CommunicationBinding b = (CommunicationBinding) stack.peek();
+ b.setChannel(chan);
+ }
+
+ /**
+ * Process the start of a read path tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a ReadPath object
+ */
+ public ReadPath processReadPath(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ ReadPath path = _arch.getReadPath(name);
+ return path;
+ }
+
+ /**
+ * Process the end of a read path tag in the XML.
+ *
+ * @param stack
+ */
+ public void processReadPath(Stack<Object> stack) {
+ ReadPath path = (ReadPath) stack.pop();
+ CommunicationBinding b = (CommunicationBinding) stack.peek();
+ b.setReadPath(path);
+ }
+
+ /**
+ * Process the start of a write path tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a WritePath object
+ */
+ public WritePath processWritePath(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ WritePath path = _arch.getWritePath(name);
+ return path;
+ }
+
+ /**
+ * Process the end of a write path tag in the XML.
+ *
+ * @param stack
+ */
+ public void processWritePath(Stack<Object> stack) {
+ WritePath path = (WritePath) stack.pop();
+ CommunicationBinding b = (CommunicationBinding) stack.peek();
+ b.setWritePath(path);
+ }
+
+ /**
+ * Process the start of a schedule tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Schedule object
+ */
+ public Schedule processSchedule(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String type = (String) attributes.getValue("type");
+ String basename = (String) attributes.getValue("basename");
+
+ Schedule schedule = new Schedule(name);
+ schedule.setSchedPolicy(SchedulingPolicy.fromString(type));
+
+ if (basename != null) schedule.setBasename(basename);
+
+ return schedule;
+ }
+
+ /**
+ * Process the end of a schedule tag in the XML.
+ *
+ * @param stack
+ */
+ public void processSchedule(Stack<Object> stack) {
+ Schedule sched = (Schedule) stack.pop();
+ Mapping map = (Mapping) stack.peek();
+ map.getScheduleList().add(sched);
+ sched.setParentResource(map);
+ }
+
+ /**
+ * Process the start of a resource tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a ArchiResource object
+ */
+ public ArchiResource processResource(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ // We are either looking for a HW channel or for a processor.
+ ArchiResource resource = null;
+ if((resource = _arch.getHWChannel(name)) == null) {
+ resource = _arch.getProcessor(name);
+ }
+ return resource;
+ }
+
+ /**
+ * Process the end of a resource tag in the XML.
+ *
+ * @param stack
+ */
+ public void processResource(Stack<Object> stack) {
+ ArchiResource resource = (ArchiResource) stack.pop();
+ Schedule schedule = (Schedule) stack.peek();
+ schedule.setResource(resource);
+ }
+
+ /**
+ * Process the start of a configuration tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Configuration object
+ */
+ public Configuration processConfiguration(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String value = (String) attributes.getValue("value");
+ Configuration config = new Configuration(name, value);
+ return config;
+ }
+
+ /**
+ * Process the end of a configuration tag in the XML.
+ *
+ * @param stack
+ */
+ public void processConfiguration(Stack<Object> stack) {
+ Configuration config = (Configuration) stack.pop();
+ if(stack.peek() instanceof ScheduleEntry) {
+ ScheduleEntry schedProc = (ScheduleEntry) stack.peek();
+ schedProc.getCfgList().add(config);
+ } else if(stack.peek() instanceof Schedule) {
+ Schedule sched = (Schedule) stack.peek();
+ sched.getCfgList().add(config);
+ }
+ }
+
+ protected ProcessNetwork _pn = null;
+ protected Architecture _arch = null;
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Mapping XML schema parser.
+This package parses the mapping XML and stores the result in internal architectural data model.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Parser for DOL specific XML files.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: PNXmlParser.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.parser.xml.pnschema;
+
+import java.util.Stack;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import dol.datamodel.XmlTag;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.parser.xml.XmlParser;
+
+/**
+ * Parse processnetwork XML file.
+ */
+public class PNXmlParser extends XmlParser {
+
+ /**
+ * Constructor.
+ */
+ public PNXmlParser() {
+ super();
+ _stack = new Stack<Object>();
+ _xml2PN = new Xml2PN();
+ }
+
+ /**
+ * Do the parsing of an XML file describing a processnetwork.
+ *
+ * @param url input XML file
+ * @return the processnetwork
+ */
+ public ProcessNetwork doParse(String url) {
+ ProcessNetwork pn = null;
+ System.out.println("Read process network from XML file");
+
+ try {
+ String uri = _makeAbsoluteURL(url);
+ _ui.printlnVerbose("-- processing XML file: " + uri);
+ _ui.printlnVerbose("-- read XML file: ");
+ _stack.clear();
+ _parser.parse(new InputSource(uri));
+ pn = (ProcessNetwork) _stack.pop();
+ _ui.printlnVerbose(" [DONE] ");
+ } catch (SAXParseException err) {
+ System.out.println("** Parsing error, line "
+ + err.getLineNumber() + ", uri " + err.getSystemId());
+ System.out.println(" " + err.getMessage());
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+
+ try {
+ pn.fillPortPeerInfo();
+ } catch (Exception e) {
+ System.out.println("Exception\n " + e.getMessage());
+ e.printStackTrace(System.out);
+ }
+
+ System.out.println(" -- Process network model from XML "
+ + "[Finished]");
+ System.out.println();
+
+ return pn;
+ }
+
+ /**
+ * Action to be done while parsing a start element of an XML.
+ *
+ * @param namespaceURI
+ * @param localName
+ * @param elementName name of element
+ * @param attributes attributes of element
+ * @exception SAXException thrown when a parsing error occurs
+ */
+ public void startElement(String namespaceURI, String localName,
+ String elementName, Attributes attributes)
+ throws SAXException {
+ Object val = null;
+
+ if (elementName.equals(_xt.getPNTag())) {
+ val = _xml2PN.processPN(attributes);
+ } else if (elementName.equals(_xt.getVariableTag())) {
+ val = _xml2PN.processVariable(attributes);
+ } else if (elementName.equals(_xt.getProcessTag())) {
+ val = _xml2PN.processProcess(attributes);
+ } else if (elementName.equals(_xt.getSWChannelTag())) {
+ val = _xml2PN.processChannel(attributes);
+ } else if (elementName.equals(_xt.getConnectionTag())) {
+ val = _xml2PN.processConnection(attributes);
+ } else if (elementName.equals(_xt.getOriginTag())) {
+ val = _xml2PN.processOrigin(attributes);
+ } else if (elementName.equals(_xt.getTargetTag())) {
+ val = _xml2PN.processTarget(attributes);
+ } else if (elementName.equals(_xt.getPortTag())) {
+ val = _xml2PN.processPort(attributes);
+ } else if (elementName.equals(_xt.getSourceTag())) {
+ val = _xml2PN.processSource(attributes);
+ } else if (elementName.equals(_xt.getProfilingTag())) {
+ val = _xml2PN.processProfiling(attributes);
+ } else if (elementName.equals(_xt.getConfigurationTag())) {
+ val = _xml2PN.processConfiguration(attributes);
+ } else {
+ System.out.println("--Warning, DOL doesn't "
+ + "understand tag <" + elementName + "> ");
+ }
+
+ if (val != null) {
+ _stack.push(val);
+ }
+ }
+
+ /**
+ * Action to be done while parsing an end element of an XML.
+ *
+ * @param elementName Description of the Parameter
+ * @exception SAXException MyException If such and such occurs
+ */
+ public void endElement(String namespaceURI, String localName,
+ String elementName) throws SAXException {
+ if (elementName.equals(_xt.getPNTag())) {
+ _xml2PN.processPN(_stack);
+ } else if (elementName.equals(_xt.getVariableTag())) {
+ _xml2PN.processVariable(_stack);
+ } else if (elementName.equals(_xt.getProcessTag())) {
+ _xml2PN.processProcess(_stack);
+ } else if (elementName.equals(_xt.getSWChannelTag())) {
+ _xml2PN.processChannel(_stack);
+ } else if (elementName.equals(_xt.getConnectionTag())) {
+ _xml2PN.processConnection(_stack);
+ } else if (elementName.equals(_xt.getOriginTag())) {
+ _xml2PN.processOrigin(_stack);
+ } else if (elementName.equals(_xt.getTargetTag())) {
+ _xml2PN.processTarget(_stack);
+ } else if (elementName.equals(_xt.getSourceTag())) {
+ _xml2PN.processSource(_stack);
+ } else if (elementName.equals(_xt.getProfilingTag())) {
+ _xml2PN.processProfiling(_stack);
+ } else if (elementName.equals(_xt.getConfigurationTag())) {
+ _xml2PN.processConfiguration(_stack);
+ } else if (elementName.equals(_xt.getPortTag())) {
+ _xml2PN.processPort(_stack);
+ }
+ }
+
+ /** stack containing the generated objects */
+ protected Stack<Object> _stack;
+
+ /** actions to be taken while parsing every XML element */
+ protected Xml2PN _xml2PN;
+
+ /** */
+ protected XmlTag _xt = XmlTag.getInstance();
+}
--- /dev/null
+/* $Id: Xml2PN.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.parser.xml.pnschema;
+
+import java.util.Stack;
+
+import org.xml.sax.Attributes;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Configuration;
+import dol.datamodel.pn.Connection;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.ProfilingConfiguration;
+import dol.datamodel.pn.Resource;
+import dol.datamodel.pn.SourceCode;
+import dol.datamodel.pn.Variable;
+
+/**
+ *
+ */
+public class Xml2PN {
+
+ /**
+ * Constructor.
+ */
+ public Xml2PN() {
+ }
+
+ /**
+ * Process the start of the process network tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a ProcessNetwork object
+ */
+ public ProcessNetwork processPN(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ ProcessNetwork p = new ProcessNetwork(name);
+ return p;
+ }
+
+ /**
+ * Process the end of the processnetwork tag in the XML.
+ *
+ * @param stack
+ */
+ public void processPN(Stack<Object> stack) {
+ }
+
+ /**
+ * Process the start of a process tag in the XML.
+ *
+ * @param attributes The attributes of the tag.
+ * @return a process object.
+ */
+ public Process processProcess(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+ Process process = new Process(name);
+ if (basename != null) process.setBasename(basename);
+ if (range != null) process.setRange(range);
+ return process;
+ }
+
+ /**
+ * Process the end of a process tag in the XML.
+ *
+ * @param stack
+ */
+ public void processProcess(Stack<Object> stack) {
+ Process p = (Process) stack.pop();
+ ProcessNetwork r = (ProcessNetwork)stack.peek();
+ r.getProcessList().add(p);
+ }
+
+ /**
+ * Process the start of a origin tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Resource object
+ */
+ public Resource processOrigin(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ Resource resource = new Resource(name);
+ if (basename != null) resource.setBasename(basename);
+ return resource;
+ }
+
+ /**
+ * Process the end of a origin tag in the XML.
+ *
+ * @param stack
+ */
+ public void processOrigin(Stack<Object> stack) {
+ Port port = (Port)stack.pop();
+ Resource resource = (Resource)stack.pop();
+ Connection connection = (Connection)stack.peek();
+
+ if(port != null) {
+ if (!port.isOutPort()) {
+ System.out.println("Error: Connection "
+ + connection.getName()
+ + " must be defined in the direction of the "
+ + " data flow!");
+ System.out.println("Exit.");
+ System.exit(-1);
+ }
+ connection.setOriginPort(port);
+ } else {
+ undefinedReference("Connection", connection.getName(),
+ "element", resource.getName());
+ }
+
+ Process process = ((ProcessNetwork)stack.elementAt(0)).
+ getProcess(resource.getName());
+ Channel channel = ((ProcessNetwork)stack.elementAt(0)).
+ getChannel(resource.getName());
+
+ if (process != null) {
+ connection.setOrigin(process);
+ }
+ else if (channel != null) {
+ connection.setOrigin(channel);
+ }
+ else {
+ undefinedReference("Connection", connection.getName(),
+ "element", resource.getName());
+ }
+ }
+
+ /**
+ * Process the start of a target tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Resource object
+ */
+ public Resource processTarget(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ Resource resource = new Resource(name);
+ if (basename != null) resource.setBasename(basename);
+ return resource;
+ }
+
+ /**
+ * Process the end of a target tag in the XML.
+ *
+ * @param stack
+ */
+ public void processTarget(Stack<Object> stack) {
+ Port port = (Port)stack.pop();
+ Resource resource = (Resource)stack.pop();
+ Connection connection = (Connection)stack.peek();
+
+ if(port != null) {
+ if (!port.isInPort()) {
+ System.out.println("Error: Connection "
+ + connection.getName()
+ + " must be defined in the direction of the "
+ + " data flow!");
+ System.out.println("Exit.");
+ System.exit(-1);
+ }
+ connection.setTargetPort(port);
+ } else {
+ undefinedReference("Connection", connection.getName(),
+ "element", resource.getName());
+ }
+
+ Process process = ((ProcessNetwork)stack.elementAt(0)).
+ getProcess(resource.getName());
+ Channel channel = ((ProcessNetwork)stack.elementAt(0)).
+ getChannel(resource.getName());
+
+ if (process != null) {
+ connection.setTarget(process);
+ }
+ else if (channel != null) {
+ connection.setTarget(channel);
+ }
+ else {
+ undefinedReference("Connection", connection.getName(),
+ "element", resource.getName());
+ }
+ }
+
+ /**
+ * Process the start of a connection tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Connection object
+ */
+ public Connection processConnection(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String basename = (String) attributes.getValue("basename");
+ Connection connection = new Connection(name);
+ if (basename != null) connection.setBasename(basename);
+ return connection;
+ }
+
+ /**
+ * Process the end of a connection tag in the XML.
+ *
+ * @param stack
+ */
+ public void processConnection(Stack<Object> stack) {
+ Connection connection = (Connection) stack.pop();
+ ProcessNetwork pn = (ProcessNetwork)stack.peek();
+ pn.getConnectionList().add(connection);
+ }
+
+ /**
+ * Process the start of a port tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Port object
+ */
+ public Port processPort(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String type = (String) attributes.getValue("type");
+ String basename = (String) attributes.getValue("basename");
+ String range = (String) attributes.getValue("range");
+
+ Port port = null;
+
+ if (type != null) {
+ if( type.equals("input") ) {
+ port = new Port(name, Port.INPORT);
+ } else if( type.equals("output") ) {
+ port = new Port(name, Port.OUTPORT);
+ }
+ } else {
+ port = new Port(name);
+ }
+
+ if (basename != null)
+ port.setBasename(basename);
+ else
+ port.setBasename(name);
+
+ if (range != null) port.setRange(range);
+
+ return port;
+ }
+
+ /**
+ * Process the end of a port tag in the XML.
+ *
+ * @param stack
+ */
+ public void processPort(Stack<Object> stack) {
+ Port port = (Port)stack.pop();
+ Resource resource = (Resource)stack.peek();
+
+ //check if this is a port or just a port reference
+ if (!(stack.elementAt(stack.size() - 2) instanceof Connection)) {
+ port.setResource(resource);
+ resource.getPortList().add(port);
+ }
+ //port reference
+ else {
+ Process process = ((ProcessNetwork)stack.elementAt(0)).
+ getProcess(resource.getName());
+ Channel channel = ((ProcessNetwork)stack.elementAt(0)).
+ getChannel(resource.getName());
+
+ Resource refResource = null;
+
+ if (process != null) {
+ refResource = process;
+ }
+ else if (channel != null) {
+ refResource = channel;
+ }
+ else {
+ undefinedReference("Connection",
+ ((Connection)stack.peek()).getName(),
+ "element", resource.getName());
+ }
+
+ Port refPort = refResource.getPort(port.getName());
+
+ if (refPort == null) {
+ undefinedReference("Connection",
+ ((Connection)stack.peek()).getName(),
+ "port", port.getName());
+ }
+
+ // Put real port back on the stack. Will be popped in
+ // processOrigin and processTarget respectively
+ stack.push(refPort);
+
+ }
+ }
+
+ /**
+ * Process the start of a channel tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Channel object
+ */
+ public Channel processChannel(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String size = (String) attributes.getValue("size");
+ String type = (String) attributes.getValue("type");
+ String tSize = (String) attributes.getValue("tokensize");
+ Channel channel = new Channel(name);
+ channel.setSize(new Integer(size));
+ channel.setTokenSize(new Integer(tSize));
+ channel.setType(type);
+ return channel;
+ }
+
+ /**
+ * Process the end of a channel tag in the XML.
+ *
+ * @param stack
+ */
+ public void processChannel(Stack<Object> stack) {
+ Channel channel = (Channel) stack.pop();
+ ProcessNetwork r = (ProcessNetwork)stack.peek();
+ r.getChannelList().add(channel);
+ }
+
+ /**
+ * Process the end of a configuration tag in the XML.
+ *
+ * @param stack
+ */
+ public void processConfiguration(Stack<Object> stack) {
+ Configuration configuration = (Configuration) stack.pop();
+ Resource r = (Resource) stack.peek();
+ configuration.setParentResource(r);
+ r.getCfgList().add(configuration);
+ }
+
+ /**
+ * Process the start of a configuration tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Configuration object
+ */
+ public Configuration processConfiguration(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String value = (String) attributes.getValue("value");
+ Configuration code = new Configuration(name);
+ code.setName(name);
+ code.setValue(value);
+ return code;
+ }
+
+ /**
+ * Process the end of a profiling tag in the XML.
+ *
+ * @param stack
+ */
+ public void processProfiling(Stack<Object> stack) {
+ ProfilingConfiguration configuration = ( ProfilingConfiguration) stack.pop();
+ Resource r = (Resource) stack.peek();
+ configuration.setParentResource(r);
+ r.getProfilingList().add(configuration);
+ }
+
+ /**
+ * Process the start of a profiling tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a profiling object
+ */
+ public Configuration processProfiling(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String value = (String) attributes.getValue("value");
+ ProfilingConfiguration code = new ProfilingConfiguration(name);
+ code.setName(name);
+ code.setValue(value);
+ return code;
+ }
+
+ /**
+ * Process the start of a channel source tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a SourceCode object
+ */
+ public SourceCode processSource(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String type = (String) attributes.getValue("type");
+ String l = (String) attributes.getValue("location");
+ SourceCode code = new SourceCode(name);
+ code.setType(type);
+ code.setLocality(l);
+ return code;
+ }
+
+ /**
+ * Process the end of a source tag in the XML.
+ *
+ * @param stack
+ */
+ public void processSource(Stack<Object> stack) {
+ SourceCode source = (SourceCode) stack.pop();
+ Process process = (Process) stack.peek();
+ source.setProcess(process);
+ process.getSrcList().add(source);
+ }
+
+ /**
+ * Process the start of a variable tag in the XML.
+ *
+ * @param attributes attributes of the tag
+ * @return a Variable object
+ */
+ public Variable processVariable(Attributes attributes) {
+ String name = (String) attributes.getValue("name");
+ String value = (String) attributes.getValue("value");
+ Variable variable = null;
+ variable = new Variable(name);
+ variable.setValue(Integer.parseInt(value));
+ return variable;
+ }
+
+ /**
+ * Process the end of a variable tag in the XML.
+ *
+ * @param stack
+ */
+ public void processVariable(Stack<Object> stack) {
+ Variable variable = (Variable) stack.pop();
+ ProcessNetwork pn = (ProcessNetwork)stack.peek();
+ variable.setParentResource(pn);
+ pn.getVarList().add(variable);
+ }
+
+ /**
+ * Write an error message and terminate program in case an
+ * processnetwork element is referenced which does not exist.
+ *
+ * @param elementType type of processnetwork element in which the error
+ * occurred
+ * @param elementName name of processnetwork element in which the error
+ * occurred
+ * @param referenceType type of referenced processnetwork element
+ * @param referenceName name of referenced processnetwork element
+ */
+ protected void undefinedReference(String elementType,
+ String elementName,
+ String referenceType,
+ String referenceName) {
+ System.out.println("Error: " + elementType + " " + elementName
+ + " references " + referenceType + " " + referenceName
+ + " that has not been declared.");
+ System.out.println("Exit.");
+ System.exit(-1);
+ }
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Process network XML schema parser.
+This package parses the process network XML and stores the result in internal data model for the process network.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: ApplicationGenerator.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.util;\r
+\r
+import java.io.BufferedWriter;\r
+import java.io.File;\r
+import java.io.FileWriter;\r
+import java.util.Random;\r
+import java.util.Vector;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import dol.datamodel.architecture.Processor;\r
+import dol.datamodel.architecture.ReadPath;\r
+import dol.datamodel.architecture.WritePath;\r
+import dol.datamodel.mapping.CommunicationBinding;\r
+import dol.datamodel.mapping.ComputationBinding;\r
+import dol.datamodel.mapping.Mapping;\r
+import dol.datamodel.mapping.Schedule;\r
+import dol.datamodel.mapping.ScheduleEntry;\r
+import dol.datamodel.mapping.SchedulingPolicy;\r
+import dol.datamodel.pn.Channel;\r
+import dol.datamodel.pn.Connection;\r
+import dol.datamodel.pn.Port;\r
+import dol.datamodel.pn.Process;\r
+import dol.datamodel.pn.ProcessNetwork;\r
+import dol.datamodel.pn.ProfilingConfiguration;\r
+import dol.datamodel.pn.SourceCode;\r
+import dol.visitor.xml.MapXmlVisitor;\r
+import dol.visitor.xml.PNXmlVisitor;\r
+\r
+/**\r
+ *\r
+ */\r
+public class ApplicationGenerator {\r
+ /*\r
+ protected String _processes[] =\r
+ {"producer", "consumer"};\r
+\r
+ protected int _computation[] =\r
+ {1000, 1000};\r
+\r
+ protected int _communication[][] =\r
+ {{0, 4}, {-4, 0}};\r
+\r
+ protected String _binding[] =\r
+ {"tile_0.arm", "tile_0.arm"};\r
+\r
+ protected int _iterations = 1000;\r
+ */\r
+\r
+ /*\r
+ protected String _processes[] =\r
+ {"producer", "forwarder", "consumer"};\r
+\r
+ protected int _computation[] =\r
+ {1000, 1000, 1000};\r
+\r
+ protected int _communication[][] =\r
+ {{ 0, 4, 0},\r
+ {-4, 0, 4},\r
+ { 0, -4, 0}};\r
+\r
+ protected String _binding[] =\r
+ {"tile_0.arm", "tile_0.arm", "tile_0.arm"};\r
+\r
+ protected int _iterations = 10;\r
+ */\r
+\r
+ /*\r
+ protected String _processes[] =\r
+ {"stageA", "stageB", "stageC", "stageD",\r
+ "stageE", "stageF", "stageG", "stageH",\r
+ "stageI", "stageJ", "stageK", "stageL",\r
+ "stageM", "stageN", "stageO", "stageP"};\r
+\r
+ protected int _computation[] =\r
+ {1, 2, 3, 4, 5, 6, 7, 8,\r
+ 9, 10, 11, 12, 13, 14, 15, 16};\r
+\r
+ protected int _communication[][] =\r
+ {{ 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ {-1024, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, -1024, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, 0, -1024, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, 0, 0, -1024, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, 0, 0, 0, -1024, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, 0, 0, 0, 0, -1024, 0, 1024, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, 0, 0, 0, 0, 0, -1024, 0, 1024, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024, 0, 0, 0, 0, 0, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024, 0, 0, 0, 0, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024, 0, 0, 0, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024, 0, 0, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024, 0, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1024, 0, 1024},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1024, 0}};\r
+\r
+\r
+ //protected String _binding[] =\r
+ // {"tile_0.arm", "tile_0.arm", "tile_1.arm", "tile_1.arm",\r
+ // "tile_2.arm", "tile_2.arm", "tile_3.arm", "tile_3.arm",\r
+ // "tile_4.arm", "tile_4.arm", "tile_5.arm", "tile_5.arm",\r
+ // "tile_6.arm", "tile_6.arm", "tile_7.arm", "tile_7.arm"};\r
+\r
+ //protected String _binding[] =\r
+ // {"tile_0.arm", "tile_1.arm", "tile_2.arm", "tile_3.arm",\r
+ // "tile_4.arm", "tile_5.arm", "tile_6.arm", "tile_7.arm",\r
+ // "tile_0.arm", "tile_1.arm", "tile_2.arm", "tile_3.arm",\r
+ // "tile_4.arm", "tile_5.arm", "tile_6.arm", "tile_7.arm"};\r
+\r
+ protected String _binding[] =\r
+ {"tile_0.arm", "tile_1.arm", "tile_2.arm", "tile_3.arm",\r
+ "tile_4.arm", "tile_5.arm", "tile_6.arm", "tile_7.arm",\r
+ "tile_7.arm", "tile_6.arm", "tile_5.arm", "tile_4.arm",\r
+ "tile_3.arm", "tile_2.arm", "tile_1.arm", "tile_0.arm"};\r
+\r
+ protected int _iterations = 10;\r
+ */\r
+\r
+ protected String _processes[] =\r
+ {"splitAA", "splitBA", "splitBB",\r
+ "pipeAA", "pipeBA", "pipeCA", "pipeDA",\r
+ "pipeEA", "pipeFA", "pipeAB", "pipeBB",\r
+ "pipeCB", "pipeDB", "pipeEB", "pipeFB",\r
+ "mergeBA", "mergeBB", "mergeAA"};\r
+\r
+ protected int _armComputation[] =\r
+ {1, 2, 3, 4, 5, 6, 7, 8,\r
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};\r
+ protected int _magicComputation[] =\r
+ {1, 2, 3, 4, 5, 6, 7, 8,\r
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};\r
+\r
+\r
+ protected int _communication[][] =\r
+ {{ 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { -4, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { -4, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, -4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0},\r
+ { 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0},\r
+ { 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0},\r
+ { 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0},\r
+ { 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0},\r
+ { 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},\r
+ { 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},\r
+ { 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},\r
+ { 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 4, 0},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -4, -4, 0, 0, 0, 0, 0, 4},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -4, -4, 0, 0, 4},\r
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -4, 0}};\r
+\r
+\r
+ //working\r
+ protected String _binding[] =\r
+ {"tile_0.arm", "tile_1.arm", "tile_4.arm",\r
+ "tile_1.arm", "tile_2.arm", "tile_3.arm", "tile_4.arm",\r
+ "tile_5.arm", "tile_6.arm", "tile_1.arm", "tile_2.arm",\r
+ "tile_3.arm", "tile_4.arm", "tile_5.arm", "tile_6.arm",\r
+ "tile_3.arm", "tile_7.arm", "tile_0.arm"};\r
+\r
+ /*\r
+ protected String _binding[] =\r
+ {"tile_0.arm", "tile_1.arm", "tile_3.arm",\r
+ "tile_1.arm", "tile_1.arm", "tile_2.arm", "tile_2.arm",\r
+ "tile_3.arm", "tile_3.arm", "tile_4.arm", "tile_4.arm",\r
+ "tile_5.arm", "tile_5.arm", "tile_6.arm", "tile_6.arm",\r
+ "tile_7.arm", "tile_7.arm", "tile_0.arm"};\r
+\r
+ protected String _binding[] =\r
+ {"tile_0.arm", "tile_1.arm", "tile_7.arm",\r
+ "tile_1.arm", "tile_1.arm", "tile_2.arm", "tile_2.arm",\r
+ "tile_3.arm", "tile_3.arm", "tile_4.arm", "tile_4.arm",\r
+ "tile_5.arm", "tile_5.arm", "tile_6.arm", "tile_6.arm",\r
+ "tile_7.arm", "tile_3.arm", "tile_0.arm"};\r
+ */\r
+\r
+ //not working\r
+ /*\r
+ protected String _binding[] =\r
+ {"tile_0.arm", "tile_1.arm", "tile_2.arm", "tile_3.arm",\r
+ "tile_4.arm", "tile_5.arm", "tile_6.arm", "tile_7.arm",\r
+ "tile_7.arm", "tile_6.arm", "tile_5.arm", "tile_4.arm",\r
+ "tile_3.arm", "tile_2.arm", "tile_1.arm", "tile_0.arm",\r
+ "tile_0.arm", "tile_0.arm"};\r
+ */\r
+\r
+ protected int _iterations = 10;\r
+\r
+ public String getStringEncoding(int i, int total) {\r
+ if (total > 26 * 26) {\r
+ System.out.println("\"total\" needs to be less than "\r
+ + 26 * 26 + ".");\r
+ return "";\r
+ } else if (total <= 26) {\r
+ return Character.toString((char)('A' + (i % 26)));\r
+ }\r
+ return Character.toString((char)('A' + (i / 26)))\r
+ + Character.toString((char)('A' + (i % 26)));\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param stages\r
+ * @param communication\r
+ */\r
+ public void generateIndependentTasks(int numberOfTasks) {\r
+ _processes = new String[numberOfTasks];\r
+ _armComputation = new int[numberOfTasks];\r
+ _magicComputation = new int[numberOfTasks];\r
+ _communication = new int[numberOfTasks][numberOfTasks];\r
+ _binding = new String[numberOfTasks];\r
+ _iterations = 1000;\r
+\r
+ for (int i = 0; i < numberOfTasks; i++) {\r
+ _processes[i] = ((i < numberOfTasks / 2) ? "armProcess"\r
+ : "magicProcess")\r
+ + getStringEncoding(i, numberOfTasks);\r
+ System.out.println(_processes[i]);\r
+ _armComputation[i] =\r
+ (i < numberOfTasks / 2) ? 100000000 : 200000000;\r
+ _magicComputation[i] =\r
+ (i < numberOfTasks / 2) ? 200000000 : 100000000;\r
+ _binding[i] = (i < numberOfTasks / 2) ? "tile_0.arm"\r
+ : "tile_0.magic";\r
+ }\r
+\r
+ //no communication\r
+ for (int i = 0; i < numberOfTasks; i++) {\r
+ for (int j = 0; j < numberOfTasks; j++) {\r
+ _communication[i][j] = 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param pipelines\r
+ * @param stages\r
+ * @param communication\r
+ */\r
+ public void generateIndpendentPipelines(int pipelines, int stages, int communication) {\r
+ Random random = new Random();\r
+ _processes = new String[stages * pipelines];\r
+ _armComputation = new int[stages * pipelines];\r
+ _magicComputation = new int[stages * pipelines];\r
+ _communication = new int[stages * pipelines][stages * pipelines];\r
+ _binding = new String[stages * pipelines];\r
+ _iterations = 1000;\r
+\r
+ for (int i = 0; i < pipelines; i++) {\r
+ for (int j = 0; j < stages; j++) {\r
+ _processes[i * stages + j] =\r
+ ((i < pipelines / 2) ? "arm" : "magic")\r
+ + "stage"\r
+ + getStringEncoding(i, pipelines) + "x"\r
+ + getStringEncoding(j, stages);\r
+ System.out.println(_processes[i * stages + j]);\r
+ _armComputation[i * stages + j] =\r
+ 0 * random.nextInt(10000000) +\r
+ ((i < pipelines / 2) ? 100000000 : 200000000);\r
+ _magicComputation[i * stages + j] =\r
+ 0 * random.nextInt(10000000) +\r
+ ((i < pipelines / 2) ? 200000000 : 100000000);\r
+ _binding[i * stages + j] = "tile_0.arm";\r
+ }\r
+ }\r
+\r
+ for (int i = 0; i < pipelines; i++) {\r
+ for (int j = 0; j < stages; j++) {\r
+ for (int k = 0; k < pipelines; k++) {\r
+ for (int l = 0; l < stages; l++) {\r
+ _communication[i * stages + j][k * stages + l] = 0;\r
+ if (i == k && l == j + 1) {\r
+ _communication[i * stages + j][k * stages + l] = communication;\r
+ } else if (i == k && j == l + 1) {\r
+ _communication[i * stages + j][k * stages + l] = -communication;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ *\r
+ * @param pipelines\r
+ * @param stages\r
+ * @param communication\r
+ */\r
+ public void generateIndpendentPipelines2(int pipelines, int stages, int communication) {\r
+ Random random = new Random();\r
+ _processes = new String[stages * pipelines];\r
+ _armComputation = new int[stages * pipelines];\r
+ _magicComputation = new int[stages * pipelines];\r
+ _communication = new int[stages * pipelines][stages * pipelines];\r
+ _binding = new String[stages * pipelines];\r
+ _iterations = 1000;\r
+\r
+ for (int i = 0; i < pipelines; i++) {\r
+ for (int j = 0; j < stages; j++) {\r
+ _processes[i * stages + j] =\r
+ ((j < stages / 2) ? "arm" : "magic")\r
+ + "stage"\r
+ + getStringEncoding(i, pipelines) + "x"\r
+ + getStringEncoding(j, stages);\r
+ System.out.println(_processes[i * stages + j]);\r
+ _armComputation[i * stages + j] =\r
+ 0 * random.nextInt(10000000) +\r
+ ((j < stages / 2) ? 100000000 : 200000000);\r
+ _magicComputation[i * stages + j] =\r
+ 0 * random.nextInt(10000000) +\r
+ ((j < stages / 2) ? 200000000 : 100000000);\r
+ _binding[i * stages + j] = "tile_0.arm";\r
+ }\r
+ }\r
+\r
+ for (int i = 0; i < pipelines; i++) {\r
+ for (int j = 0; j < stages; j++) {\r
+ for (int k = 0; k < pipelines; k++) {\r
+ for (int l = 0; l < stages; l++) {\r
+ _communication[i * stages + j][k * stages + l] = 0;\r
+ if (i == k && l == j + 1) {\r
+ _communication[i * stages + j][k * stages + l] = communication;\r
+ } else if (i == k && j == l + 1) {\r
+ _communication[i * stages + j][k * stages + l] = -communication;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ *\r
+ * @param stages\r
+ * @param communication\r
+ */\r
+ public void generatePipeline(int stages, int communication) {\r
+ _processes = new String[stages];\r
+ _armComputation = new int[stages];\r
+ _magicComputation = new int[stages];\r
+ _communication = new int[stages][stages];\r
+ _binding = new String[stages];\r
+ //_iterations = 1000;\r
+ _iterations = 1000;\r
+\r
+ for (int i = 0; i < stages; i++) {\r
+ _processes[i] = ((i % 8 < 4) ? "arm" : "magic")\r
+ + "stage" + getStringEncoding(i, stages);\r
+ System.out.println(_processes[i]);\r
+ _armComputation[i] =\r
+ (i % 8 < 4) ? 100 : 200;\r
+ _magicComputation[i] =\r
+ (i % 8 < 4) ? 200 : 100;\r
+ _binding[i] = "tile_0.arm";\r
+ }\r
+\r
+ for (int i = 0; i < stages; i++) {\r
+ for (int j = 0; j < stages; j++) {\r
+ _communication[i][j] = 0;\r
+ if (j == i + 1) {\r
+ _communication[i][j] = communication;\r
+ } else if (i == j + 1) {\r
+ _communication[i][j] = -communication;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ *\r
+ * @param pn\r
+ */\r
+ public void generateProcessNetwork(ProcessNetwork pn) {\r
+ System.out.print("Generate process network. ");\r
+ int numberOfProcesses = 0;\r
+ int numberOfChannels = 0;\r
+\r
+ for (int j = 0; j < _processes.length; j++) {\r
+ String processName = _processes[j];\r
+ Process p = new Process(processName);\r
+ SourceCode srcCode = new SourceCode(processName);\r
+ srcCode.setLocality(processName + ".c");\r
+ srcCode.setType("c");\r
+ p.getSrcList().add(srcCode);\r
+ pn.getProcessList().add(p);\r
+ numberOfProcesses++;\r
+ for (int i = 0; i < 8; i++) {\r
+ ProfilingConfiguration c = new ProfilingConfiguration(\r
+ "BCED tile_" + i + ".arm");\r
+ c.setValue(Integer.toString(_armComputation[j]));\r
+ p.getProfilingList().add(c);\r
+ c = new ProfilingConfiguration(\r
+ "BCED tile_" + i + ".magic");\r
+ c.setValue(Integer.toString(_magicComputation[j]));\r
+ p.getProfilingList().add(c);\r
+ }\r
+ }\r
+\r
+ //check whether communication matrix is symmetric\r
+ if (_communication[0].length != numberOfProcesses) {\r
+ System.out.println();\r
+ System.out.println("Error: Size of communication matrix ("\r
+ + _communication[0].length + " columns) must match "\r
+ + "number of processes (" + numberOfProcesses + ").");\r
+ System.exit(-1);\r
+ }\r
+ for (int row = 0; row < numberOfProcesses; row++) {\r
+ for (int col = 0; col < numberOfProcesses; col++) {\r
+ if (row == col && _communication[row][col] != 0) {\r
+ System.out.println();\r
+ System.out.println("Error: No self-channels allowed. "\r
+ + "Problem for process " + row + " ("\r
+ + _processes[row] + ").");\r
+ System.exit(-1);\r
+ }\r
+ if (_communication[row][col] !=\r
+ -_communication[col][row]) {\r
+ System.out.println();\r
+ System.out.println("Error: Communication matrix "\r
+ + "needs to be symmetric. Mismatch for row "\r
+ + row + " column " + col + ".");\r
+ System.exit(-1);\r
+ }\r
+ }\r
+ }\r
+\r
+ for (int row = 0; row < numberOfProcesses; row++) {\r
+ for (int col = row; col < numberOfProcesses; col++) {\r
+ if (_communication[row][col] == 0) {\r
+ continue;\r
+ }\r
+ int src = row;\r
+ int dst = col;\r
+\r
+ if (_communication[row][col] < 0) {\r
+ src = col;\r
+ dst = row;\r
+ }\r
+\r
+ Channel c = new Channel("channel" + _processes[src]\r
+ + _processes[dst]);\r
+ c.setSize(Math.abs(2 * _communication[src][dst]));\r
+ c.setType("fifo");\r
+ ProfilingConfiguration p = new ProfilingConfiguration(\r
+ "TotalReadData");\r
+ p.setValue(Integer.toString(_communication[row][col]));\r
+ c.getProfilingList().add(p);\r
+ pn.getChannelList().add(c);\r
+ numberOfChannels++;\r
+\r
+ Port channelPort0 = new Port("0", Port.INPORT);\r
+ Port channelPort1 = new Port("1", Port.OUTPORT);\r
+ c.getPortList().add(channelPort0);\r
+ c.getPortList().add(channelPort1);\r
+\r
+ Connection c1 = new Connection(\r
+ "c1" + _processes[src] + _processes[dst]);\r
+ Connection c2 = new Connection(\r
+ "c2" + _processes[src] + _processes[dst]);\r
+ pn.getConnectionList().add(c1);\r
+ pn.getConnectionList().add(c2);\r
+\r
+ Port p0 = new Port(Integer.toString(pn.getProcess(\r
+ _processes[src]).getPortList().size()),\r
+ Port.OUTPORT);\r
+ Port p1 = new Port(Integer.toString(pn.getProcess(\r
+ _processes[dst]).getPortList().size()),\r
+ Port.INPORT);\r
+ pn.getProcess(_processes[src]).getPortList().add(p0);\r
+ pn.getProcess(_processes[dst]).getPortList().add(p1);\r
+\r
+ c1.setOriginPort(p0);\r
+ c1.setTargetPort(channelPort0);\r
+ c1.setOrigin(pn.getProcess(_processes[src]));\r
+ c1.setTarget(c);\r
+ p0.setPeerResource(c);\r
+ p0.setPeerPort(channelPort0);\r
+ channelPort0.setPeerResource(pn.getProcess(\r
+ _processes[src]));\r
+ channelPort0.setPeerPort(p0);\r
+\r
+ c2.setOriginPort(channelPort1);\r
+ c2.setTargetPort(p1);\r
+ c2.setOrigin(c);\r
+ c2.setTarget(pn.getProcess(_processes[dst]));\r
+ channelPort1.setPeerResource(pn.getProcess(\r
+ _processes[dst]));\r
+ channelPort1.setPeerPort(p1);\r
+ p1.setPeerResource(c);\r
+ p1.setPeerPort(channelPort1);\r
+\r
+ c.setOrigin(pn.getProcess(_processes[src]));\r
+ c.setTarget(pn.getProcess(_processes[dst]));\r
+ }\r
+ }\r
+\r
+ System.out.println("Finished.");\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param pn\r
+ */\r
+ public void generateProcessNetworkXml(ProcessNetwork pn,\r
+ String filename) {\r
+ System.out.print("Generate process network XML. ");\r
+ StringBuffer buffer = new StringBuffer();\r
+ pn.accept(new PNXmlVisitor(buffer));\r
+ try {\r
+ java.io.BufferedWriter writer =\r
+ new java.io.BufferedWriter(\r
+ new java.io.FileWriter(filename));\r
+ writer.write(buffer.toString());\r
+ writer.close();\r
+ } catch (java.io.IOException e) {\r
+ System.out.println();\r
+ System.out.println("Error: Could not write XML file.");\r
+ System.exit(-1);\r
+ }\r
+ System.out.println("Finished.");\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param pn\r
+ * @param path\r
+ */\r
+ public void generateCode(ProcessNetwork pn, String path) {\r
+ System.out.print("Generate source code of processes. ");\r
+\r
+ String newline = System.getProperty("line.separator");\r
+ int maxProcessNameLength = 0;\r
+ for (String processName : _processes) {\r
+ maxProcessNameLength = Math.max(maxProcessNameLength,\r
+ processName.length());\r
+ }\r
+\r
+ String global = "";\r
+ global += "#ifndef GLOBAL_H" + newline;\r
+ global += "#define GLOBAL_H" + newline;\r
+ global += newline;\r
+\r
+ global += "#define ITERATIONS " + _iterations + newline;\r
+ global += newline;\r
+\r
+ for (int i = 0; i < _processes.length; i++) {\r
+ global += "#define LOOPS_ARM_" + _processes[i].toUpperCase()\r
+ + " " + _armComputation[i] + newline;\r
+ global += "#define LOOPS_MAGIC_" + _processes[i].toUpperCase()\r
+ + " " + _magicComputation[i] + newline;\r
+ }\r
+\r
+ for (int row = 0; row < _communication[0].length; row++) {\r
+ for (int col = row; col < _communication[0].length; col++) {\r
+ if (_communication[row][col] == 0) {\r
+ continue;\r
+ }\r
+ int src = row;\r
+ int dst = col;\r
+\r
+ if (_communication[row][col] < 0) {\r
+ src = col;\r
+ dst = row;\r
+ }\r
+\r
+ global += "#define TOKEN_SIZE_"\r
+ + _processes[src].toUpperCase() + "_"\r
+ + _processes[dst].toUpperCase() + " "\r
+ + _communication[src][dst] + newline;\r
+ }\r
+ }\r
+ global += newline;\r
+ global += "#endif" + newline;\r
+\r
+ try {\r
+ BufferedWriter out = new BufferedWriter(\r
+ new FileWriter(path + "global.h"));\r
+ out.write(global);\r
+ out.close();\r
+ } catch (Exception e) {\r
+ System.out.println();\r
+ System.out.println("Error: While writing global.h file.");\r
+ System.exit(-1);\r
+ }\r
+\r
+\r
+ for (Process p : pn.getProcessList()) {\r
+ String state = p.getName().substring(0, 1).toUpperCase()\r
+ + p.getName().substring(1) + "_State";\r
+\r
+ String h = "";\r
+ h += "#ifndef " + p.getName().toUpperCase() + "_H" + newline;\r
+ h += "#define " + p.getName().toUpperCase() + "_H" + newline;\r
+ h += newline;\r
+ h += "#include <dol.h>" + newline;\r
+ h += newline;\r
+ for (Port port : p.getPortList()) {\r
+ h += "#define PORT_" + p.getName().toUpperCase() + "_"\r
+ + (port.isInPort() ? "IN_" : "OUT_" )\r
+ + port.getName() + " " + port.getName() + newline;\r
+ }\r
+ h += newline;\r
+ h += "typedef struct {" + newline;\r
+ h += " int iterations;" + newline;\r
+ h += "} " + state + ";" + newline;\r
+ h += newline;\r
+ h += "void " + p.getName() + "_init(DOLProcess *p);"\r
+ + newline;\r
+ h += "int " + p.getName() + "_fire(DOLProcess *p);" + newline;\r
+ h += newline;\r
+ h += "#endif" + newline;\r
+\r
+ String c = "";\r
+ String printPrefix = String.format(" printf(\"[%-"\r
+ + maxProcessNameLength + "s] ", p.getName());\r
+ c += "#include <stdio.h>" + newline;\r
+ c += newline;\r
+ c += "#include \"" + p.getName() + ".h\"" + newline;\r
+ c += "#include \"global.h\"" + newline;\r
+ c += newline;\r
+ c += "void " + p.getName() + "_init(DOLProcess *p) {"\r
+ + newline;\r
+ c += " " + state + " *state = (" + state + "*)p->local;"\r
+ + newline;\r
+ c += " state->iterations = 0;" + newline;\r
+ c += "}" + newline;\r
+ c += newline;\r
+ c += "int " + p.getName() + "_fire(DOLProcess *p) {"\r
+ + newline;\r
+\r
+ int processIndex = getProcessIndex(p.getName());\r
+ int maxBuffer = 0;\r
+ for (int i = 0; i < _communication[processIndex].length; i++) {\r
+ maxBuffer = Math.max(maxBuffer,\r
+ Math.abs(_communication[processIndex][i]));\r
+ }\r
+ c += " int buffer[" + ((maxBuffer + (4 - 1)) / 4) + "];" + newline;\r
+ c += " int i;" + newline;\r
+ c += " " + state + " *state = (" + state + "*)p->local;";\r
+ c += newline + newline;\r
+\r
+ for (Port port : p.getPortList()) {\r
+ if (port.isInPort()) {\r
+ int originIndex = getProcessIndex(\r
+ ((Channel)port.getPeerResource()).getOrigin()\r
+ .getName());\r
+ String tokenSize = "TOKEN_SIZE_"\r
+ + _processes[originIndex].toUpperCase() + "_"\r
+ + _processes[processIndex].toUpperCase();\r
+ c += printPrefix + "read %d bytes from "\r
+ + _processes[originIndex] + ".\\n\", " + tokenSize\r
+ + ");" + newline;\r
+ c += " DOL_read((void*)"\r
+ + "PORT_" + p.getName().toUpperCase() + "_IN_"\r
+ + port.getName() + ", buffer, " + tokenSize\r
+ + ", p);" + newline;\r
+ }\r
+ }\r
+ c += newline;\r
+ //c += " printf(\"[%-20s ] iteration %d/n\", \""\r
+ // + p.getName() + "\", state->iterations);" + newline;\r
+ c += printPrefix + "iteration %d.\\n\" , "\r
+ + "state->iterations);" + newline;\r
+ c += newline;\r
+ c += "#ifdef __arm__" + newline;\r
+ c += " for (i = 0; i < LOOPS_ARM_" + p.getName().toUpperCase()\r
+ + "; i++) { ; }" + newline;\r
+ c += "#else" + newline;\r
+ c += " for (i = 0; i < LOOPS_MAGIC_" + p.getName().toUpperCase()\r
+ + "; i++) { ; }" + newline;\r
+ c += "#endif" + newline;\r
+ for (Port port : p.getPortList()) {\r
+ if (port.isOutPort()) {\r
+ int targetIndex = getProcessIndex(\r
+ ((Channel)port.getPeerResource()).getTarget()\r
+ .getName());\r
+ String tokenSize = "TOKEN_SIZE_"\r
+ + _processes[processIndex].toUpperCase() + "_"\r
+ + _processes[targetIndex].toUpperCase();\r
+ c += printPrefix + "write %d bytes to "\r
+ + _processes[targetIndex] + ".\\n\", " + tokenSize\r
+ + ");" + newline;\r
+ c += " DOL_write((void*)"\r
+ + "PORT_" + p.getName().toUpperCase() + "_OUT_"\r
+ + port.getName() + ", buffer, "+ tokenSize\r
+ + ", p);" + newline;\r
+ }\r
+ }\r
+ c += newline;\r
+ c += " state->iterations++;" + newline;\r
+ c += " if (state->iterations >= ITERATIONS) {"\r
+ + newline;\r
+ c += " DOL_detach(p);" + newline;\r
+ c += " return -1;" + newline;\r
+ c += " }" + newline;\r
+ c += newline;\r
+ c += " return 0;" + newline;\r
+ c += "}" + newline;\r
+\r
+ try {\r
+ BufferedWriter out = new BufferedWriter(\r
+ new FileWriter(path + p.getName() + ".h"));\r
+ out.write(h);\r
+ out.close();\r
+ out = new BufferedWriter(\r
+ new FileWriter(path + p.getName() + ".c"));\r
+ out.write(c);\r
+ out.close();\r
+ } catch (Exception e) {\r
+ System.out.println();\r
+ System.out.println("Error: While writing source files.");\r
+ System.exit(-1);\r
+ }\r
+ }\r
+ System.out.println("Finished.");\r
+ }\r
+\r
+\r
+ /**\r
+ *\r
+ * @param map\r
+ * @param pn\r
+ */\r
+ public void generateMapping(ProcessNetwork pn, Mapping map) {\r
+ System.out.print("Generate mapping. ");\r
+ map.setPN(pn);\r
+\r
+ //binding of processes\r
+ Vector<Processor> processors = new Vector<Processor>();\r
+ for (int i = 0; i < _binding.length; i++) {\r
+ String processName = _processes[i];\r
+ String processorName = _binding[i];\r
+ Processor processor = null;\r
+\r
+ boolean processorExists = false;\r
+ for (Processor proc : processors) {\r
+ if (proc.getName().equals(processorName)) {\r
+ processor = proc;\r
+ processorExists = true;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!processorExists) {\r
+ processor = new Processor(processorName);\r
+ processors.add(processor);\r
+ }\r
+\r
+ ComputationBinding compBinding = new ComputationBinding(\r
+ processName + "binding");\r
+ compBinding.setProcess(pn.getProcess(processName));\r
+ compBinding.setProcessor(processor);\r
+ processor.getProcessList().add(pn.getProcess(processName));\r
+ map.getCompBindList().add(compBinding);\r
+ }\r
+\r
+ //schedules\r
+ for (Processor p : processors) {\r
+ Schedule s = new Schedule(p.getName() + "schedule");\r
+ s.setSchedPolicy(SchedulingPolicy.FIFO);\r
+ s.setResource(p);\r
+ for (Process process : p.getProcessList()) {\r
+ ScheduleEntry entry = new ScheduleEntry(\r
+ process.getName());\r
+ entry.setConsumer(process);\r
+ s.getEntryList().add(entry);\r
+ }\r
+ map.getScheduleList().add(s);\r
+ }\r
+\r
+ //binding of channels\r
+ for (Channel c : pn.getChannelList()) {\r
+ String originProcess = c.getOrigin().getName();\r
+ String targetProcess = c.getTarget().getName();\r
+\r
+ String originBinding = _binding[getProcessIndex(\r
+ originProcess)];\r
+ String targetBinding = _binding[getProcessIndex(\r
+ targetProcess)];\r
+\r
+ Pattern pattern0 = Pattern.compile(\r
+ "tile_(\\d)\\.(arm)|tile_(\\d)\\.(magic)");\r
+ Matcher matcher0 = pattern0.matcher(originBinding);\r
+ Pattern pattern1 = Pattern.compile(\r
+ "tile_(\\d)\\.(arm)|tile_(\\d)\\.(magic)");\r
+ Matcher matcher1 = pattern1.matcher(targetBinding);\r
+\r
+ if (!matcher0.matches() || !matcher1.matches()) {\r
+ System.out.println("binding needs to comply to the"\r
+ + " following regular expression: "\r
+ + "tile_(\\d)\\.(arm)|tile_(\\d)\\.(magic)");\r
+ System.exit(-1);\r
+ }\r
+\r
+ int srcIndex = Integer.valueOf(matcher0.group(1));\r
+ int dstIndex = Integer.valueOf(matcher1.group(1));\r
+ String srcProcessor = matcher0.group(2);\r
+ String dstProcessor = matcher1.group(2);\r
+\r
+ String writePath = "";\r
+ String readPath = "";\r
+\r
+ if (srcIndex == dstIndex) {\r
+ if (srcProcessor.equals("arm")) {\r
+ writePath = "tile_" + srcIndex + ".rdmtodxm";\r
+ } else {\r
+ writePath = "tile_" + srcIndex + ".ddmtodxm";\r
+ }\r
+ } else {\r
+ if (srcProcessor.equals("arm")) {\r
+ writePath = "tile_" + srcIndex + ".rdmtodnp_"\r
+ + dstIndex;\r
+ } else {\r
+ writePath = "tile_" + srcIndex + ".ddmtodnp_"\r
+ + dstIndex;\r
+ }\r
+ }\r
+\r
+ if (dstProcessor.equals("arm")) {\r
+ readPath = "tile_" + dstIndex + ".rdmfromdxm";\r
+ } else {\r
+ readPath = "tile_" + dstIndex + ".ddmfromdxm";\r
+ }\r
+\r
+ CommunicationBinding commBinding = new CommunicationBinding(\r
+ c.getName() + "binding");\r
+ commBinding.setChannel(c);\r
+ commBinding.setWritePath(new WritePath(writePath));\r
+ commBinding.setReadPath(new ReadPath(readPath));\r
+ map.getCommBindList().add(commBinding);\r
+ }\r
+ System.out.println("Finished.");\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param processName\r
+ * @return\r
+ */\r
+ protected int getProcessIndex(String processName) {\r
+ for (int i = 0; i < _processes.length; i++) {\r
+ if (_processes[i].equals(processName)) {\r
+ return i;\r
+ }\r
+ }\r
+ System.out.println("Error: Could not find process "\r
+ + processName + ".");\r
+ System.exit(-1);\r
+ return 0;\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param map\r
+ */\r
+ public void generateMappingXml(Mapping map, String filename) {\r
+ System.out.print("Generate mapping XML. ");\r
+ StringBuffer buffer = new StringBuffer();\r
+ map.accept(new MapXmlVisitor(buffer));\r
+ try {\r
+ java.io.BufferedWriter writer =\r
+ new java.io.BufferedWriter(\r
+ new java.io.FileWriter(filename));\r
+ writer.write(buffer.toString());\r
+ writer.close();\r
+ } catch (java.io.IOException e) {\r
+ System.out.println("Could not write XML file.");\r
+ System.exit(-1);\r
+ }\r
+ System.out.println("Finished.");\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param args\r
+ */\r
+ public static void main(String args[]) {\r
+ /*\r
+ Pattern pattern = Pattern.compile("tile_(\\d)\\.");\r
+ Matcher matcher = pattern.matcher("tile_3.");\r
+ matcher.matches();\r
+ System.out.println(matcher.group(1));\r
+ */\r
+\r
+ String appName = "exampleAuto";\r
+ String path = System.getProperty("user.dir") + "/" + appName + "/";\r
+ File dir = new File(path);\r
+ dir.mkdirs();\r
+ dir = new File(path + "src/");\r
+ dir.mkdirs();\r
+\r
+ System.out.println("Generate application \"" + appName + "\""\r
+ + " in directory \"" + path + "\".");\r
+ ApplicationGenerator appGen = new ApplicationGenerator();\r
+ //appGen.generateIndpendentPipelines2(16, 4, 10000000);\r
+ appGen.generatePipeline(64, 10);\r
+ //appGen.generateIndependentTasks(64);\r
+ ProcessNetwork pn = new ProcessNetwork(appName);\r
+ appGen.generateProcessNetwork(pn);\r
+ appGen.generateProcessNetworkXml(pn, path + appName + ".xml");\r
+ appGen.generateCode(pn, path + "src/");\r
+ Mapping map = new Mapping("mapping");\r
+ appGen.generateMapping(pn, map);\r
+ appGen.generateMappingXml(map, path + "mapping.xml");\r
+ System.out.println("Done.");\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/* $Id: CheckXMLs.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.util;\r
+\r
+import dol.datamodel.architecture.Architecture;\r
+import dol.datamodel.mapping.Mapping;\r
+import dol.datamodel.pn.ProcessNetwork;\r
+import dol.parser.xml.archischema.ArchiXmlParser;\r
+import dol.parser.xml.mapschema.MapXmlParser;\r
+import dol.parser.xml.pnschema.PNXmlParser;\r
+\r
+\r
+public class CheckXMLs {\r
+ public static void main(String args[]) {\r
+\r
+ /*\r
+ String pnFile = "D:\\shapes\\pa\\tools\\exampleTest.xml";\r
+ String archFile = "D:\\shapes\\pa\\tools\\rdt8.xml";\r
+ String mapFile = "D:\\shapes\\pa\\tools\\mapping_2tiles.xml";\r
+ */\r
+ String pnFile = "processnetwork.xml";\r
+ String archFile = "rdt8.xml";\r
+ String mapFile = "mapping.xml";\r
+\r
+ if (args.length == 3) {\r
+ pnFile = args[0];\r
+ archFile = args[1];\r
+ mapFile = args[2];\r
+ }\r
+\r
+ System.out.println("Process network: " + pnFile);\r
+ System.out.println("Architecture: " + archFile);\r
+ System.out.println("Mapping: " + mapFile);\r
+ PNXmlParser parserPn = new PNXmlParser();\r
+ ProcessNetwork pn = parserPn.doParse(pnFile);\r
+\r
+ ArchiXmlParser parserArch = new ArchiXmlParser();\r
+ Architecture arch = parserArch.doParse(archFile);\r
+\r
+ MapXmlParser parserMap = new MapXmlParser(pn, arch);\r
+ Mapping mapping = parserMap.doParse(mapFile);\r
+\r
+ mapping.getArch();\r
+ System.out.println("XML files seem to be consistent.");\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/* $Id: CodePrintStream.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.util;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+/**
+ * Class to print code that is correctly indented.
+ */
+public class CodePrintStream extends PrintStream {
+
+ /**
+ *
+ */
+ public CodePrintStream(OutputStream out) {
+ super(out);
+ }
+
+ /**
+ *
+ */
+ public CodePrintStream(OutputStream out, boolean autoFlush) {
+ super(out, autoFlush);
+ }
+
+ /**
+ *
+ */
+ public void print(String x) {
+ super.print(x);
+ }
+
+ /**
+ *
+ */
+ public void println(String x) {
+ super.println(x);
+ }
+
+ /**
+ *
+ */
+ public void printPrefix(String x) {
+ super.print(_prefix + x);
+ }
+
+ /**
+ *
+ */
+ public void printPrefix() {
+ super.print(_prefix);
+ }
+
+ /**
+ *
+ */
+ public void printPrefixln(String x) {
+ super.println(_prefix + x);
+ }
+
+ /**
+ *
+ */
+ public void printPrefixln() {
+ super.println();
+ }
+
+ /**
+ * Print an opening curly brace and increase the indentation.
+ */
+ public void printLeftBracket() {
+ printPrefix();
+ println("{");
+ prefixInc();
+ }
+
+ /**
+ * Decrease the indentation and print a closing curly brace.
+ */
+ public void printRightBracket() {
+ prefixDec();
+ printPrefixln("}");
+ }
+
+ /**
+ * Decrement the indentation.
+ */
+ public void prefixDec() {
+ if( _prefix.length() >= _offset.length() ) {
+ _prefix = _prefix.substring(_offset.length());
+ }
+ }
+
+ /**
+ * Increment the indentation.
+ */
+ public void prefixInc() {
+ _prefix += _offset;
+ }
+
+ /**
+ *
+ */
+ public static void main(String[] args) {
+ CodePrintStream ps = new CodePrintStream(System.out);
+ ps.println("aa");
+ ps.print("bb");
+ }
+
+ private static String _offset = " ";
+ private String _prefix = "";
+}
+
+
+
--- /dev/null
+/* $Id: CodePrintString.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.util;
+
+/**
+ * Class to print code that is correctly indented.
+ */
+public class CodePrintString {
+
+ /**
+ * Default constructor.
+ *
+ * @param stringBuffer string buffer where the result is stored
+ */
+ public CodePrintString(StringBuffer stringBuffer) {
+ _code = stringBuffer;
+ }
+
+ /**
+ * Print a line without indentation.
+ */
+ public void print(String string) {
+ _code.append(string);
+ }
+
+ /**
+ * Add a line break to the current line. Results in an empty
+ * line if the current line is empty.
+ */
+ public void println() {
+ _code.append(System.getProperty("line.separator"));
+ }
+
+ /**
+ * Print a line without indentation and add a line break.
+ * @param string string to print
+ */
+ public void println(String string) {
+ _code.append(string + System.getProperty("line.separator"));
+ }
+
+ /**
+ * Print spaces according to current level of indentation.
+ */
+ public void printPrefix() {
+ _code.append(_prefix);
+ }
+
+ /**
+ * Print a line at the current level of indentation.
+ * @param string string to print
+ */
+ public void printPrefix(String string) {
+ _code.append(_prefix + string);
+ }
+
+ /**
+ * Print a line at the current level of indentation and a line break.
+ * @param string string to print
+ */
+ public void printPrefixln(String string) {
+ _code.append(_prefix + string
+ + System.getProperty("line.separator"));
+ }
+
+ /**
+ * Print the opening tag for the given XML tag name and increase
+ * the indentation.
+ * @param tagName name of the XML tag
+ */
+ public void printOpeningTag(String tagName) {
+ printPrefix();
+ print("<" + tagName);
+ prefixInc();
+ }
+
+ /**
+ * Decrease the indentation and print the closing tag for the given
+ * XML tag name.
+ * @param tagName name of the XML tag
+ */
+ public void printClosingTag(String tagName) {
+ prefixDec();
+ printPrefixln("</" + tagName + ">");
+ }
+
+ /**
+ * Decrement the indentation.
+ */
+ public void prefixDec() {
+ if( _prefix.length() >= _offset.length() ) {
+ _prefix = _prefix.substring(_offset.length());
+ }
+ }
+
+ /**
+ * Increment the indentation.
+ */
+ public void prefixInc() {
+ _prefix += _offset;
+ }
+
+ /**
+ * Get the formatted output string.
+ * @return output string
+ */
+ public String toString() {
+ return _code.toString();
+ }
+
+ /**
+ * Test the CodePrintString implementation.
+ */
+ public static void main(String[] args) {
+ StringBuffer buffer = new StringBuffer();
+ CodePrintString ps = new CodePrintString(buffer);
+ ps.printOpeningTag("tag");
+ ps.println(">");
+ ps.printPrefixln("<abc/>");
+ ps.printClosingTag("tag");
+ System.out.println(ps.toString());
+ }
+
+ protected static String _offset = " ";
+ protected String _prefix = "";
+ protected StringBuffer _code = null;
+}
+
+
+
--- /dev/null
+/* $Id: Copier.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.util.jar.JarFile;
+
+/**
+ * Class to recursively copy a directory.
+ */
+public class Copier {
+
+ String _destination; //target directory
+
+ /**
+ * Copy a file.
+ *
+ * @param from source file
+ * @param to destination file
+ */
+ public void copyFile(File from, File to)
+ throws IOException {
+
+ FileChannel srcChannel = new FileInputStream(from).getChannel();
+ FileChannel dstChannel = new FileOutputStream(to).getChannel();
+ try {
+ dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
+ srcChannel.close();
+ dstChannel.close();
+ }
+ finally {
+ if (srcChannel != null)
+ srcChannel.close();
+
+ if (dstChannel != null)
+ dstChannel.close();
+ }
+ }
+
+ /**
+ * Method which defines what is done for each file found in the
+ * directory tree: It is copied to the corresponding target directory.
+ *
+ * @param filename file to process
+ * @param directory the subdirectory currently processed
+ */
+ protected void processFile(String filename, String directory)
+ throws IOException {
+ File from = new File(filename);
+ File to = new File(_destination + directory + from.getName());
+ copyFile(from, to);
+ //System.out.println("Copied " + from.getPath() + " to "
+ // + to.getPath());
+ }
+
+ /**
+ * Iterate through the given directory tree. For each file found in
+ * the file, the method
+ * {@link #processFile(java.lang.String, java.lang.String)} is called.
+ *
+ * @param path the path of the directory to be browsed
+ * @param currentDir the subdirectory currently explored
+ */
+ protected void browseDirectoryTree(String path, String currentDir)
+ throws IOException {
+ File file = new File(path);
+
+ if (!file.exists()) return;
+ if (!file.isDirectory()) return;
+
+ //loop through files in directory
+ String[] files = file.list();
+
+ for (int k = 0; k < files.length; k++) {
+ File newfile = new File(file.getPath(), files[k]);
+ if (newfile.isFile())
+ processFile(path + System.getProperty("file.separator")
+ + files[k], currentDir);
+ else if (newfile.isDirectory()) {
+ File newDirectory = new File(_destination + currentDir
+ + files[k]);
+ newDirectory.mkdirs();
+ //System.out.println("Created directory "
+ // + newDirectory.getPath());
+ browseDirectoryTree(file.getPath()
+ + System.getProperty("file.separator")
+ + files[k], currentDir + files[k]
+ + System.getProperty("file.separator"));
+ }
+ }
+ }
+
+ /**
+ * Recursively copy a directory.
+ *
+ * @param source source directory
+ * @param destination target directory
+ */
+ public void copy(File source, File destination)
+ throws IOException {
+ try {
+ //treat jar archives differently
+ if (source.toString().contains("dol.jar!")) {
+ String jarName = source.toString();
+ jarName = jarName.substring(jarName.indexOf("file:") + 5, jarName.lastIndexOf("!"));
+ String sourceName = source.toString();
+ sourceName = sourceName.substring(
+ sourceName.lastIndexOf("!") + 2);
+ sourceName = sourceName.replaceAll("\\\\", "/");
+
+ JarFile jar = new JarFile(jarName);
+ JarCopier copier = new JarCopier();
+ copier.copy(jar, sourceName, destination.toString());
+ return;
+ }
+
+ _destination = destination.getPath();
+
+ if (!source.isDirectory())
+ throw (new IOException("Source is not a directory."));
+
+ File destinationDir = new File(_destination);
+ destinationDir.mkdirs();
+
+ browseDirectoryTree(source.getPath(),
+ System.getProperty("file.separator"));
+ }
+ catch (IOException e) {
+ System.out.println("An error has occured while copying \""
+ + source.getPath() + "\" to \""
+ + destination.getPath() + "\":");
+ System.out.println(e.getMessage());
+ throw e;
+ }
+ }
+
+ /**
+ * Test the implementation.
+ *
+ * @param args args[0] specifies the source directory,
+ * args[1] specifies the destination directory
+ */
+ public static void main(String args[])
+ throws Exception {
+ Copier copier = new Copier();
+ if (args.length == 2)
+ copier.copy(new File(args[0]), new File(args[1]));
+ else
+ System.out.println("usage: java Copier "
+ + "sourceDirectory targetDirectory");
+ }
+}
--- /dev/null
+/* $Id: JarCopier.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.util;\r
+\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.util.Enumeration;\r
+import java.util.Vector;\r
+import java.util.jar.JarEntry;\r
+import java.util.jar.JarFile;\r
+\r
+/**\r
+ * Class to copy files from a jar archive.\r
+ */\r
+public class JarCopier {\r
+\r
+ /**\r
+ * Copy a file from the specified jar file to the specified\r
+ * destination file. The file path must be specified using forward\r
+ * slashes, for instance, META-INF/MANIFEST.MF.\r
+ *\r
+ * @param jar jar archive\r
+ * @param from file to extract from jar archive\r
+ * @param to file to copy the file to\r
+ */\r
+ public void copyFile(JarFile jar, String from, String to) {\r
+ try {\r
+ InputStream in = jar.getInputStream(jar.getEntry(from));\r
+ OutputStream out = new FileOutputStream(new File(to));\r
+ int c;\r
+ while ((c = in.read()) != -1) {\r
+ out.write(c);\r
+ }\r
+ in.close();\r
+ out.close();\r
+ }\r
+ catch (IOException e) {\r
+ System.out.println("An error has occured while copying \""\r
+ + from + "\" to \"" + to + "\":");\r
+ System.out.println(e.getMessage());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get all files located in the given path of the given jar archive.\r
+ * The path must be specified with forward slashes.\r
+ *\r
+ * @param jar jar archive\r
+ * @param path path to search for files\r
+ * @return vector of all files in the specified path\r
+ */\r
+ public Vector<String> getFilesInDirectory(JarFile jar, String path) {\r
+ Vector<String> filelist = new Vector<String>();\r
+ Enumeration<JarEntry> entries = jar.entries();\r
+\r
+ while (entries.hasMoreElements()) {\r
+ String entry = entries.nextElement().toString();\r
+ if (entry.startsWith(path)) {\r
+ filelist.add(entry);\r
+ }\r
+ }\r
+ return filelist;\r
+ }\r
+\r
+ /**\r
+ * Recursively copy a directory from the specified jar archive.\r
+ *\r
+ * @param jar jar archive\r
+ * @param srcDir source directory\r
+ * @param destDir target directory\r
+ */\r
+ public void copy(JarFile jar, String srcDir, String destDir)\r
+ throws IOException {\r
+ File directory = new File(destDir);\r
+ if (!directory.exists()) {\r
+ directory.mkdirs();\r
+ }\r
+ for (String file : getFilesInDirectory(jar, srcDir)) {\r
+ String dir = file.substring(0, file.lastIndexOf("/"));\r
+ directory = new File(destDir\r
+ + System.getProperty("file.separator")\r
+ + dir.substring(srcDir.length()));\r
+ if (!directory.exists()) {\r
+ directory.mkdirs();\r
+ }\r
+ if (!file.endsWith("/")) {\r
+ copyFile(jar, file, destDir\r
+ + System.getProperty("file.separator")\r
+ + file.substring(srcDir.length() + 1));\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Copy the specified directory from the jar archive to the specified\r
+ * destination.\r
+ *\r
+ * @param args args[0] specifies the jar file to read from,\r
+ * args[1] specifies the source directory,\r
+ * args[2] specifies the destination directory\r
+ */\r
+ public static void main(String args[])\r
+ throws Exception {\r
+ JarCopier copier = new JarCopier();\r
+ JarFile jar = new JarFile(args[0]);\r
+ if (args.length == 3)\r
+ copier.copy(jar, args[1], args[2]);\r
+ else\r
+ System.out.println("usage: java JarCopier "\r
+ + "jarFile sourceDirectory targetDirectory");\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/* $Id: SchemaLocation.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.util;
+
+/**
+ * Class to get the location of schemas.
+ */
+public class SchemaLocation {
+
+ protected static final String PN_NAMESPACE =
+ "http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK";
+ protected static final String PN_LOCATION =
+ "http://www.tik.ee.ethz.ch/~shapes/schema/processnetwork.xsd";
+ protected static final String ARCH_NAMESPACE =
+ "http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE";
+ protected static final String ARCH_LOCATION =
+ "http://www.tik.ee.ethz.ch/~shapes/schema/architecture.xsd";
+ protected static final String ARCH_NAMESPACE_OLD =
+ "http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE_OLD";
+ protected static final String MAP_NAMESPACE =
+ "http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING";
+ protected static final String MAP_LOCATION =
+ "http://www.tik.ee.ethz.ch/~shapes/schema/mapping.xsd";
+ protected static final String MAP_NAMESPACE_OLD =
+ "http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING_OLD";
+
+ /** singleton instance */
+ protected final static SchemaLocation _schemaLocation =
+ new SchemaLocation();
+
+ /**
+ * Default constructor.
+ */
+ public SchemaLocation() {
+ }
+
+ /**
+ * Return the process network namespace.
+ *
+ * @return process network namespace
+ */
+ public static String getProcessNetworkNamespace() {
+ return PN_NAMESPACE;
+ }
+
+ /**
+ * Return the process network schema location.
+ *
+ * @return process network schema location
+ */
+ public static String getProcessNetworkSchemaLocation() {
+ return PN_LOCATION;
+ }
+
+ /**
+ * Return the architecture namespace.
+ *
+ * @return architecture namespace
+ */
+ public static String getArchitectureNamespace() {
+ return ARCH_NAMESPACE;
+ }
+
+ /**
+ * Return the architecture schema location.
+ *
+ * @return architecture schema location
+ */
+ public static String getArchitectureSchemaLocation() {
+ return ARCH_LOCATION;
+ }
+
+ /**
+ * Return the mapping namespace.
+ *
+ * @return mapping namespace
+ */
+ public static String getMappingNamespace() {
+ return MAP_NAMESPACE;
+ }
+
+ /**
+ * Return the mapping schema location.
+ *
+ * @return mapping schema location
+ */
+ public static String getMappingSchemaLocation() {
+ return MAP_LOCATION;
+ }
+
+ /**
+ * Return a string with the references to the external schema files.
+ *
+ * @return references to external schemas
+ */
+ public static String getExternalSchemaLocation() {
+ String loc = PN_NAMESPACE + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/processnetwork.xsd");
+ loc += " " + ARCH_NAMESPACE + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/architecture.xsd");
+ loc += " " + ARCH_NAMESPACE_OLD + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/architecture_old.xsd");
+ loc += " " + MAP_NAMESPACE + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/mapping.xsd");
+ return loc;
+ }
+
+ /**
+ * Return a string with the references to the internal schema files.
+ *
+ * @return references to internal schemas
+ */
+ public static String getInternalSchemaLocation() {
+ String loc = PN_NAMESPACE + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/internal/processnetwork_internal.xsd");
+ loc += " " + ARCH_NAMESPACE + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/internal/architecture_internal.xsd");
+ loc += " " + ARCH_NAMESPACE_OLD + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/internal/architecture_old_internal.xsd");
+ loc += " " + MAP_NAMESPACE + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/internal/mapping_internal.xsd");
+ loc += " " + MAP_NAMESPACE_OLD + " ";
+ loc += _schemaLocation.getClass().getResource(
+ "/schema/internal/mapping_old_internal.xsd");
+ return loc;
+ }
+}
+
+
+
--- /dev/null
+/* $Id: Sed.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.util;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.BufferedWriter;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileWriter;\r
+import java.io.IOException;\r
+import java.io.InputStreamReader;\r
+\r
+/**\r
+ * Class to find and replace strings in a files of a directory.\r
+ * The intention is to get a behavior similar to UNIX's sed (stream\r
+ * editor).\r
+ */\r
+public class Sed {\r
+\r
+ /**\r
+ * In the given file, search for occurences of the given search\r
+ * pattern and replace it by the given replacement.\r
+ * searchPattern, replacementPattern will be used in a call of\r
+ * String.replaceAll(searchPattern, replacementPattern).\r
+ *\r
+ * @param filename file to search\r
+ * @param searchPattern regular expression to search for\r
+ * @param replacementPattern replacement\r
+ */\r
+ protected void readReplace(String filename, String searchPattern,\r
+ String replacementPattern) throws IOException {\r
+ String line;\r
+ StringBuffer buffer = new StringBuffer();\r
+ FileInputStream fileInputStream = new FileInputStream(filename);\r
+ BufferedReader reader = new BufferedReader(\r
+ new InputStreamReader(fileInputStream));\r
+ while((line = reader.readLine()) != null) {\r
+ String newline = line.replaceAll(searchPattern, replacementPattern);\r
+ /*\r
+ if (!newline.equals(line)) {\r
+ System.out.println("Found pattern in " + filename\r
+ + ". New line: " + newline);\r
+ }\r
+ */\r
+ buffer.append(newline + "\n");\r
+ }\r
+ reader.close();\r
+ BufferedWriter out = new BufferedWriter(new FileWriter(filename));\r
+ out.write(buffer.toString());\r
+ out.close();\r
+ }\r
+\r
+ /**\r
+ * Iterate through the given directory tree. For each file found in\r
+ * the file, the method\r
+ * {@link #processFile(java.lang.String)} is called.\r
+ *\r
+ * @param path the path of the directory to be browsed\r
+ * @param currentDir the subdirectory currently explored\r
+ */\r
+ protected void browseDirectoryTree(String path)\r
+ throws IOException {\r
+ File file = new File(path);\r
+\r
+ if (!file.exists()) return;\r
+ if (!file.isDirectory()) return;\r
+\r
+ //loop through files in directory\r
+ String[] files = file.list();\r
+\r
+ for (int k = 0; k < files.length; k++) {\r
+ File newfile = new File(file.getPath(), files[k]);\r
+ if (newfile.isFile())\r
+ readReplace(path + System.getProperty("file.separator")\r
+ + files[k], _searchPattern, _replacementPattern);\r
+ else if (newfile.isDirectory()) {\r
+ browseDirectoryTree(file.getPath()\r
+ + System.getProperty("file.separator")\r
+ + files[k]);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * In the given file or in the files located in the given directory,\r
+ * search for occurences of the given search pattern and replace it\r
+ * by the given replacement. searchPattern, replacementPattern will\r
+ * be used in a call of\r
+ * String.replaceAll(searchPattern, replacementPattern).\r
+ *\r
+ * @param path file or path to search\r
+ * @param searchPattern regular expression to search for\r
+ * @param replacementPattern replacement\r
+ */\r
+ public void sed(String path, String searchPattern,\r
+ String replacementPattern) throws IOException {\r
+ File file = new File(path);\r
+ _searchPattern = searchPattern;\r
+ _replacementPattern = replacementPattern;\r
+ if (!file.exists()) return;\r
+ if (file.isFile()) {\r
+ readReplace(path, searchPattern, replacementPattern);\r
+ }\r
+ else if (file.isDirectory()) {\r
+ browseDirectoryTree(path);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Test the implementation.\r
+ *\r
+ * @param args args[0] file or directory to search\r
+ * args[1] regular expression to search for\r
+ * args[2] replacement\r
+ */\r
+ public static void main(String args[]) {\r
+ if (args.length == 3) {\r
+ try {\r
+ new Sed().sed(args[0], args[1], args[2]);\r
+ }\r
+ catch (IOException e) {\r
+ System.out.println("Sed: An error occured:");\r
+ System.out.println(e.getMessage());\r
+ }\r
+ }\r
+ else {\r
+ System.out.println("usage: java Sed directory|file "\r
+ + "searchPattern replacementPattern");\r
+ }\r
+ }\r
+\r
+ String _searchPattern = "";\r
+ String _replacementPattern = "";\r
+}\r
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Collection of tools for file operations.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: ArchiVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor;
+
+import dol.datamodel.architecture.ArchiConnection;
+import dol.datamodel.architecture.ArchiResource;
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.architecture.Configuration;
+import dol.datamodel.architecture.HWChannel;
+import dol.datamodel.architecture.Memory;
+import dol.datamodel.architecture.Node;
+import dol.datamodel.architecture.PortNode;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.architecture.ReadPath;
+import dol.datamodel.architecture.Variable;
+import dol.datamodel.architecture.WritePath;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+
+/**
+ * This class is an abstract class for a visitor that is used to
+ * generate an Archietcture description.
+ */
+public abstract class ArchiVisitor implements Visitor {
+
+ public ArchiVisitor() {
+ _ui = UserInterface.getInstance();
+ }
+
+ public void visitComponent(Architecture x) { }
+ public void visitComponent(ArchiResource x) { }
+ public void visitComponent(Processor x) { }
+ public void visitComponent(Memory x) { }
+ public void visitComponent(HWChannel x) { }
+ public void visitComponent(Configuration x) {}
+ public void visitComponent(Variable x) { }
+ public void visitComponent(Node x) { }
+ public void visitComponent(PortNode x) { }
+ public void visitComponent(ArchiConnection x) {}
+ public void visitComponent(ReadPath x) {}
+ public void visitComponent(WritePath x) {}
+
+ /**
+ * Stream where the print output is sent to.
+ */
+ protected CodePrintStream _printStream = null;
+ protected UserInterface _ui = null;
+}
--- /dev/null
+/* $Id: MapVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor;
+
+import dol.datamodel.mapping.Binding;
+import dol.datamodel.mapping.CommunicationBinding;
+import dol.datamodel.mapping.ComputationBinding;
+import dol.datamodel.mapping.Configuration;
+import dol.datamodel.mapping.MapResource;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.mapping.Schedule;
+import dol.datamodel.mapping.ScheduleEntry;
+import dol.datamodel.mapping.Variable;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+
+/**
+ * This class is an abstract class for a visitor that is used to
+ * generate a mapping description.
+ */
+public abstract class MapVisitor implements Visitor {
+
+ public MapVisitor() {
+ _ui = UserInterface.getInstance();
+ }
+
+ public void visitComponent(Mapping x) { }
+ public void visitComponent(MapResource x) { }
+ public void visitComponent(Binding x) {}
+ public void visitComponent(ComputationBinding x) {}
+ public void visitComponent(CommunicationBinding x) {}
+ public void visitComponent(Schedule x) {}
+ public void visitComponent(ScheduleEntry x) {}
+ public void visitComponent(Variable x) {}
+ public void visitComponent(Configuration x) {}
+
+ /**
+ * Stream where the print output is sent to.
+ */
+ protected CodePrintStream _printStream = null;
+ protected UserInterface _ui = null;
+}
--- /dev/null
+/* $Id: PNVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Configuration;
+import dol.datamodel.pn.Connection;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.ProfilingConfiguration;
+import dol.datamodel.pn.Resource;
+import dol.datamodel.pn.SourceCode;
+import dol.datamodel.pn.Variable;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+
+/**
+ * This class is an abstract class for a visitor that is used to
+ * generate a Process Network description.
+ */
+public abstract class PNVisitor implements Visitor {
+
+ public PNVisitor() {
+ _ui = UserInterface.getInstance();
+ }
+
+ public void visitComponent(ProcessNetwork x) { }
+ public void visitComponent(Resource x) { }
+ public void visitComponent(Process x) { }
+ public void visitComponent(Variable x) { }
+ public void visitComponent(Channel x) { }
+ public void visitComponent(Connection x) { }
+ public void visitComponent(Configuration x) { }
+ public void visitComponent(ProfilingConfiguration x) { }
+ public void visitComponent(Port x) { }
+ public void visitComponent(SourceCode x) { }
+
+ /**
+ * Stream where the print output is sent to.
+ */
+ protected CodePrintStream _printStream = null;
+ protected UserInterface _ui = null;
+ protected String _delimiter = "/";
+}
--- /dev/null
+/* $Id: PipeAndFilterMakefileVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.PipeAndFilter;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class PipeAndFilterMakefileVisitor extends PNVisitor {
+
+ /**
+ *
+ */
+ public PipeAndFilterMakefileVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ ps.println("CXX = g++");
+ ps.println("CXXFLAGS = -g -Wall");
+ ps.println("COMPILE = ${CXX} ${CXXFLAGS} -c");
+ ps.println("LINK = ${CXX} -lpthread");
+ ps.println("LIB_INC = -Ilib -Iwrappers -Iprocesses");
+ ps.println();
+ ps.println("src := $(wildcard lib/*.cpp) "
+ + "$(wildcard wrappers/*.cpp) $(wildcard *.cpp)");
+ ps.println("obj = $(src:.cpp=.o)");
+ ps.println();
+ ps.println("app : ${obj} ${src}");
+ ps.println("\t${LINK} -o " + _name + " $(obj)");
+ ps.println();
+ ps.println("%.o :");
+ ps.println("\t${COMPILE} -o $(*D)/$(*F).o $(*D)/$(*F).cpp $(LIB_INC)");
+ ps.println();
+ ps.println("clean :");
+ ps.println("\trm ${obj}");
+ }
+ catch (IOException e) {
+ System.out.println(" PipeAndFilter Makefile Visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ protected String _name = "sc_application";
+
+}
+
--- /dev/null
+/* $Id: PipeAndFilterModuleVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.PipeAndFilter;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.Resource;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * the main program.
+ */
+public class PipeAndFilterModuleVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public PipeAndFilterModuleVisitor(String dir) {
+ _dir = dir;
+ }
+
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "sc_application.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ _code = new CodePrintStream(file);
+
+ _code.println("#include <iostream>");
+ _code.println();
+
+ _code.printPrefixln("#include \"lib/Fifo.h\"");
+ _code.printPrefixln("#include \"lib/Scheduler.h\"");
+ _code.printPrefixln("#include \"lib/WindowedFifo.h\"");
+ _code.println();
+ _code.printPrefixln("#include \"wrappers/wrappers.h\"");
+ _code.println();
+ _code.printPrefixln("#include \"processnetwork.h\"");
+ _code.println();
+ _code.printPrefixln("int main(void)");
+ _code.printLeftBracket();
+
+ _code.printPrefixln("std::map<std::string, "
+ + "ProcessWrapper* > *processes");
+ _code.printPrefixln(" = new std::map<std::string, "
+ + "ProcessWrapper* >();");
+ _code.println();
+
+ _code.printPrefixln("Scheduler *scheduler = "
+ + "new Scheduler();");
+ _code.println();
+
+ //instantiate channels
+ for (Channel c : x.getChannelList()) {
+ if (c.getType().equals("fifo")) {
+ printProcessNetwork("Fifo *" + c.getName()
+ + " = new Fifo(\"" + c.getName()
+ + "\", " + c.getSize() * c.getTokenSize()
+ + ");");
+ } else if (c.getType().equals("wfifo")) {
+ printProcessNetwork("WindowedFifo *" + c.getName()
+ + " = new WindowedFifo(\"" + c.getName()
+ + "\", " + c.getSize() * c.getTokenSize()
+ + ");");
+ }
+ }
+ printProcessNetwork("");
+
+ // instantiate processes and connect to channels
+ for (Process p : x.getProcessList()) {
+ printProcessNetwork(p.getBasename() + "_wrapper *"
+ + p.getName() + " = new "
+ + p.getBasename() + "_wrapper(\""
+ + p.getName() + "\");");
+ printProcessNetwork("processes->insert(std::pair"
+ + "<std::string, ProcessWrapper* >(\""
+ + p.getName() + "\", " + p.getName() + "));");
+ printProcessNetwork("");
+ }
+
+ //build the network
+ for (Channel ch : x.getChannelList()) {
+ ch.accept(this);
+ }
+
+ printProcessNetwork("}");
+
+ String headerfilename = _dir + _delimiter
+ + "processnetwork.h";
+ OutputStream headerfile = new FileOutputStream(
+ headerfilename);
+ CodePrintStream processnetworkHeader = new
+ CodePrintStream(headerfile);
+ processnetworkHeader.printPrefixln(
+ "#ifndef PROCESSNETWORK_H");
+ processnetworkHeader.printPrefixln(
+ "#define PROCESSNETWORK_H");
+ processnetworkHeader.println();
+
+ for (int counter = 1; counter <= _processNetworkCounter;
+ counter++) {
+ _code.printPrefixln("processnetwork_part"
+ + String.format("%03d", counter) + "::create("
+ + "processes);");
+ processnetworkHeader.println("#include "
+ + "\"processnetwork_part"
+ + String.format("%03d", counter) + ".h\"");
+ }
+ _code.println();
+
+ processnetworkHeader.println();
+ processnetworkHeader.printPrefixln("#endif");
+
+
+ //register processes
+ _code.printPrefixln("std::map<std::string, "
+ + "ProcessWrapper* >::iterator process_iterator;");
+ _code.printPrefixln("for (process_iterator = "
+ + "processes->begin();");
+ _code.printPrefixln(" process_iterator != "
+ + "processes->end();");
+ _code.printPrefixln(" process_iterator++) {");
+ _code.printPrefixln(" scheduler->registerProcess("
+ + "static_cast<ProcessWrapper* >");
+ _code.printPrefixln(" ((*process_iterator).second));");
+ _code.printPrefixln("}");
+ _code.println();
+
+ //run scheduler
+ _code.printPrefixln("scheduler->run();");
+ _code.println();
+
+ //clean up
+ _code.println();
+ _code.printPrefixln("for (process_iterator = "
+ + "processes->begin();");
+ _code.printPrefixln(" process_iterator != "
+ + "processes->end();");
+ _code.printPrefixln(" process_iterator++) {");
+ _code.printPrefixln(" delete static_cast<ProcessWrapper* >"
+ + "((*process_iterator).second);");
+ _code.printPrefixln("}");
+ _code.println();
+ //_code.printPrefixln("std::cout << \"End.\" << std::endl;");
+ _code.printPrefixln("return 0;");
+ _code.printRightBracket();
+ }
+ catch (Exception e) {
+ System.out.println("PipeAndFilterModuleVisitor: "
+ + "exception occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void createProcessNetworkHeader(int part)
+ throws IOException {
+ String partString = String.format("%03d", part);
+ String filename = _dir + _delimiter + "processnetwork_part"
+ + partString + ".h";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream header = new CodePrintStream(file);
+
+ header.println("#ifndef PROCESSNETWORK_PART"
+ + partString + "_H");
+ header.println("#define PROCESSNETWORK_PART"
+ + partString + "_H");
+ header.println();
+ header.println("#include <map>");
+ header.println("#include <string>");
+ header.println();
+ header.println("#include \"lib/ProcessWrapper.h\"");
+ header.println("#include \"lib/Fifo.h\"");
+ header.println("#include \"lib/WindowedFifo.h\"");
+ header.println();
+ header.println("#include \"wrappers/wrappers.h\"");
+ header.println();
+ header.println("class processnetwork_part" + partString + " {");
+ header.println(" public:");
+ header.println(" processnetwork_part"
+ + partString + "();");
+ header.println(" virtual ~processnetwork_part"
+ + partString + "();");
+ header.println(" static void create(");
+ header.println(" std::map<std::string, "
+ + "ProcessWrapper* > *processes);");
+ header.println("};");
+ header.println();
+ header.println("#endif");
+ }
+
+
+ /**
+ *
+ */
+ protected void printProcessNetwork(String nextLine)
+ throws IOException {
+ if (!_fileOpen ||
+ (_numberOfLines >= MAX_NUMBER_OF_LINES &&
+ !nextLine.contains("->insert") &&
+ !nextLine.equals("") &&
+ !nextLine.contains("Port(") &&
+ !nextLine.contains("<std::string, Port* >"))) {
+
+ if (_fileOpen) {
+ _pn.printRightBracket();
+ }
+
+ _processNetworkCounter++;
+ _numberOfLines = 0;
+ createProcessNetworkHeader(_processNetworkCounter);
+ String partString = String.format("%03d",
+ _processNetworkCounter);
+ String processNetworkFilename = _dir + _delimiter
+ + "processnetwork_part" + partString + ".cpp";
+
+ _file = new FileOutputStream(processNetworkFilename);
+ _pn = new CodePrintStream(_file);
+ _fileOpen = true;
+
+ _pn.printPrefixln("#include \"processnetwork_part"
+ + partString + ".h\"");
+ _pn.println();
+
+ _pn.printPrefixln("processnetwork_part" + partString
+ + "::processnetwork_part" + partString + "() {");
+ _pn.printPrefixln(" //nothing to do");
+ _pn.printPrefixln("}");
+ _pn.println();
+ _pn.printPrefixln("processnetwork_part" + partString
+ + "::~processnetwork_part" + partString + "() {");
+ _pn.printPrefixln(" //nothing to do");
+ _pn.printPrefixln("}");
+ _pn.println();
+ _pn.printPrefixln("void processnetwork_part" + partString
+ + "::create(");
+ _pn.printPrefixln(" std::map<std::string, "
+ + "ProcessWrapper* > *processes)");
+ _pn.printLeftBracket();
+ }
+
+ _pn.printPrefixln(nextLine);
+ _numberOfLines++;
+ }
+
+ /**
+ *
+ * @param x channel that needs to be rendered
+ */
+ public void visitComponent(Channel x) {
+ try {
+ for (Port p : x.getPortList()) {
+ Port peerPort = (Port)(p.getPeerPort());
+ Resource peerResource = p.getPeerResource();
+ String codeLine = "";
+ if (peerPort.getRange() != null) {
+ if (p.isOutPort()) {
+ codeLine = peerResource.getName()
+ + "->INPORT_"
+ + peerPort.getBasename()
+ + peerPort.getName().replaceAll(
+ "_([0-9]+)", "[$1]").replaceFirst(
+ peerPort.getBasename(), "");
+ }
+ else if (p.isInPort()) {
+ codeLine = peerResource.getName()
+ + "->OUTPORT_"
+ + peerPort.getBasename()
+ + peerPort.getName().replaceAll(
+ "_([0-9]+)", "[$1]").replaceFirst(
+ peerPort.getBasename(), "");
+ }
+ }
+ else {
+ if (p.isOutPort()) {
+ codeLine = peerResource.getName()
+ + "->INPORT_" + peerPort.getName();
+ }
+ else if (p.isInPort()) {
+ codeLine = peerResource.getName()
+ + "->OUTPORT_" + peerPort.getName();
+ }
+ }
+ printProcessNetwork(codeLine + " = " + x.getName() + ";");
+ }
+ }
+ catch (Exception e) {
+ System.out.println("PipeAndFilterModuleVisitor: "
+ + "exception occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected CodePrintStream _code = null;
+ protected String _dir = null;
+ protected boolean _fileOpen = false;
+ protected int _processNetworkCounter = 0;
+ protected int _numberOfLines = 0;
+ protected static final int MAX_NUMBER_OF_LINES = 1000;
+ protected OutputStream _file;
+ protected CodePrintStream _pn;
+}
+
--- /dev/null
+/* $Id: PipeAndFilterProcessVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.PipeAndFilter;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+import dol.visitor.hds.HdsProcessVisitor;
+
+/**
+ *
+ */
+public class PipeAndFilterProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public PipeAndFilterProcessVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork x) {
+ HdsProcessVisitor visitor = new HdsProcessVisitor(_dir);
+ x.accept(visitor);
+
+ try {
+ String filename = _dir + _delimiter + "wrappers.h";
+ OutputStream file = new FileOutputStream(filename);
+ _wrapperHeader = new CodePrintStream(file);
+ _wrapperHeader.printPrefixln("#ifndef WRAPPERS_H");
+ _wrapperHeader.printPrefixln("#define WRAPPERS_H");
+ _wrapperHeader.println();
+ Vector<String> pList = new Vector<String>();
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ pList.add(basename);
+ _wrapperHeader.printPrefixln("#include \""
+ + p.getBasename() + "_wrapper.h\"");
+ }
+ }
+ _wrapperHeader.println();
+ _wrapperHeader.printPrefixln("#endif");
+ } catch (Exception e) {
+ System.out.println("Process Visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ CodePrintStream _wrapperHeader;
+}
--- /dev/null
+/* $Id: PipeAndFilterVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.PipeAndFilter;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.Copier;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class PipeAndFilterVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public PipeAndFilterVisitor(String packageName) {
+ _packageName = packageName;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ _generateDirHierarchy();
+
+ x.accept(new PipeAndFilterMakefileVisitor(_srcDir));
+ x.accept(new PipeAndFilterModuleVisitor(_srcDir));
+ x.accept(new PipeAndFilterProcessVisitor(_wrapperDir));
+
+ } catch (Exception e) {
+ System.out.println(" SystemC PN Visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ *
+ */
+ private void _generateDirHierarchy()
+ throws IOException, FileNotFoundException {
+
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ _srcDir = _packageName + _delimiter + _srcDirName;
+ dir = new File(_srcDir);
+ dir.mkdirs();
+
+ _libDir = _srcDir + _delimiter + _libDirName;
+ dir = new File(_libDir);
+ dir.mkdirs();
+
+ _processDir = _srcDir + _delimiter + _processDirName;
+ dir = new File(_processDir);
+ dir.mkdirs();
+
+ _wrapperDir = _srcDir + _delimiter + _wrapperDirName;
+ dir = new File(_wrapperDir);
+ dir.mkdirs();
+
+ // copy library
+ String libraryPath = _ui.getMySystemCLib();
+ libraryPath = libraryPath.replaceAll("systemC",
+ "PipeAndFilter");
+ File source = new File(libraryPath);
+ File destination = new File(_libDir);
+ new Copier().copy(source, destination);
+
+ //copy process src code
+ source = new File(_srcDirName);
+ destination = new File(_processDir);
+ new Copier().copy(source, destination);
+ }
+
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+
+ protected String _libDir = "";
+ protected static String _libDirName = "lib";
+
+ protected String _processDir = "";
+ protected static String _processDirName = "processes";
+
+ protected String _wrapperDir = "";
+ protected static String _wrapperDirName = "wrappers";
+}
+
--- /dev/null
+#include "Condition.h"\r
+\r
+Condition::Condition(Mutex *mutex) {\r
+ //std::cout << "Create Condition." << std::endl;\r
+ _mutex = mutex;\r
+ _condition = new pthread_cond_t;\r
+ pthread_cond_init(_condition, NULL);\r
+}\r
+\r
+\r
+Condition::~Condition() {\r
+ //std::cout << "Delete Condition." << std::endl;\r
+ pthread_cond_destroy(_condition);\r
+ delete _condition;\r
+ //std::cout << "Deleted Condition." << std::endl;\r
+}\r
+\r
+\r
+void Condition::notify() {\r
+ pthread_cond_signal(_condition);\r
+}\r
+\r
+\r
+void Condition::notifyAll() {\r
+ pthread_cond_broadcast(_condition);\r
+}\r
+\r
+\r
+void Condition::wait() {\r
+ pthread_cond_wait(_condition, _mutex->getPThreadMutex());\r
+}\r
--- /dev/null
+#ifndef _CONDITION_H_\r
+#define _CONDITION_H_\r
+\r
+#include <iostream>\r
+#include <pthread.h>\r
+#include "Mutex.h"\r
+\r
+class Condition {\r
+ public:\r
+ Condition(Mutex *mutex);\r
+ virtual ~Condition();\r
+ virtual void notify();\r
+ virtual void notifyAll();\r
+ virtual void wait();\r
+\r
+ protected:\r
+ Mutex *_mutex;\r
+ pthread_cond_t *_condition;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#include "Event.h"\r
+\r
+Event::Event() {\r
+ _name = "Event";\r
+ //std::cout << "Create " << _name << "." << std::endl;\r
+ _mutex = new Mutex();\r
+ _condition = new Condition(_mutex);\r
+ _waitMutex = new Mutex();\r
+ _waitCondition = new Condition(_waitMutex);\r
+ _pendingWait = false;\r
+}\r
+\r
+\r
+Event::Event(std::string name) {\r
+ _name = "Event " + name;\r
+ //std::cout << "Create " << _name << "." << std::endl;\r
+ _mutex = new Mutex();\r
+ _condition = new Condition(_mutex);\r
+ _waitMutex = new Mutex();\r
+ _waitCondition = new Condition(_waitMutex);\r
+ _pendingWait = false;\r
+}\r
+\r
+\r
+Event::~Event() {\r
+ //std::cout << "Delete " << _name << "." << std::endl;\r
+ delete _condition;\r
+ delete _waitCondition;\r
+ delete _mutex;\r
+ delete _waitMutex;\r
+ //std::cout << "Deleted " << _name << "." << std::endl;\r
+}\r
+\r
+\r
+void Event::notify() {\r
+ _mutex->lock();\r
+ _condition->notify();\r
+ _mutex->unlock();\r
+}\r
+\r
+\r
+void Event::notifyAll() {\r
+ _mutex->lock();\r
+ _condition->notifyAll();\r
+ _mutex->unlock();\r
+}\r
+\r
+\r
+void Event::wait() {\r
+ _mutex->lock();\r
+ _pendingWait = true;\r
+ _waitMutex->lock();\r
+ _waitCondition->notify();\r
+ _waitMutex->unlock();\r
+ _condition->wait();\r
+ _pendingWait = false;\r
+ _mutex->unlock();\r
+}\r
+\r
+\r
+void Event::notifyAfterWait() {\r
+ _mutex->lock();\r
+\r
+ if (!_pendingWait) {\r
+ _waitMutex->lock();\r
+ _mutex->unlock();\r
+ _waitCondition->wait();\r
+ _mutex->lock();\r
+ _waitMutex->unlock();\r
+ }\r
+ _condition->notify();\r
+ _mutex->unlock();\r
+}\r
--- /dev/null
+#ifndef _EVENT_H_\r
+#define _EVENT_H_\r
+\r
+#include <iostream>\r
+#include <string>\r
+#include <pthread.h>\r
+#include "Mutex.h"\r
+#include "Condition.h"\r
+\r
+class Event {\r
+ public:\r
+ Event();\r
+ Event(std::string name);\r
+ Event(Mutex *mutex);\r
+ virtual ~Event();\r
+ virtual void notify();\r
+ virtual void notifyAll();\r
+ virtual void wait();\r
+ virtual void notifyAfterWait();\r
+\r
+ protected:\r
+ Mutex *_mutex;\r
+ Condition *_condition;\r
+ Mutex *_waitMutex;\r
+ Condition *_waitCondition;\r
+ bool _pendingWait;\r
+ std::string _name;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#include "Fifo.h"\r
+\r
+/**\r
+ *\r
+ */\r
+Fifo::Fifo(char* name, unsigned size = 18) {\r
+ //std::cout << "Create Fifo." << std::endl;\r
+ //except at the beginning, _head and _tail must never overlap,\r
+ //otherwise one does not know whether the buffer is full or\r
+ //empty. to have nevertheless a buffer with the given capacity,\r
+ //a buffer with one more element is allocated.\r
+ _size = size + 1;\r
+ _buffer = new char[_size];\r
+ _head = 0;\r
+ _tail = 0;\r
+ _name = new char[strlen(name) + 1];\r
+ strcpy(_name, name);\r
+ _mutex = new Mutex();\r
+ _readCondition = new Condition(_mutex);\r
+ _writeCondition = new Condition(_mutex);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+Fifo::~Fifo() {\r
+ //std::cout << "Delete Fifo." << std::endl;\r
+ if (_buffer) {\r
+ delete _buffer;\r
+ }\r
+ if (_name) {\r
+ delete _name;\r
+ }\r
+ if (_readCondition) {\r
+ delete _readCondition;\r
+ }\r
+ if (_writeCondition) {\r
+ delete _writeCondition;\r
+ }\r
+ if (_mutex) {\r
+ delete _mutex;\r
+ }\r
+\r
+ _buffer = 0;\r
+ _head = 0;\r
+ _tail = 0;\r
+ _name = 0;\r
+ _readCondition = 0;\r
+ _writeCondition = 0;\r
+ _mutex = 0;\r
+ //std::cout << "Deleted Fifo." << std::endl;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::read(void *destination, unsigned len) {\r
+ char* buffer = (char*)destination;\r
+ unsigned read = 0;\r
+ //std::cout << "Try to read " << len << " bytes from Fifo " << _name << "." << std::endl;\r
+\r
+ while (read < len) {\r
+ _mutex->lock();\r
+ while (used() == 0) {\r
+ _writeCondition->wait();\r
+ }\r
+ _mutex->unlock();\r
+\r
+ if ((len - read) < used()) {\r
+ while (read < len) {\r
+ _mutex->lock();\r
+ unsigned tocopy = (len - read + _tail >= _size) ? _size - _tail : len - read;\r
+ memcpy(buffer, _buffer + _tail, tocopy);\r
+ _tail = (_tail + tocopy) % _size;\r
+ read += tocopy;\r
+ buffer += tocopy;\r
+ _mutex->unlock();\r
+ }\r
+ _readCondition->notify();\r
+ } else {\r
+ _mutex->lock();\r
+ *buffer++ = *(_buffer + _tail % _size);\r
+ _tail = (_tail + 1) % _size;\r
+ read++;\r
+ _mutex->unlock();\r
+ _readCondition->notify();\r
+ }\r
+ }\r
+\r
+ //std::cout << "Read " << read << " bytes from Fifo " << _name << "." << std::endl;\r
+ return read;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::write(const void *source, unsigned len) {\r
+ char* buffer = (char*)source;\r
+ unsigned write = 0;\r
+ //std::cout << "Try to write " << len << " bytes to Fifo " << _name << std::endl;\r
+\r
+ while (write < len) {\r
+ _mutex->lock();\r
+ while (unused() == 0) {\r
+ _readCondition->wait();\r
+ }\r
+ _mutex->unlock();\r
+\r
+ if ((len - write) < unused()) {\r
+ while (write < len) {\r
+ unsigned tocopy = (len - write + _head >= _size) ? _size - _head : len - write;\r
+ _mutex->lock();\r
+ memcpy(_buffer + _head, buffer, tocopy);\r
+ _head = (_head + tocopy) % _size;\r
+ write += tocopy;\r
+ buffer += tocopy;\r
+ _mutex->unlock();\r
+ }\r
+ _writeCondition->notify();\r
+ } else {\r
+ _mutex->lock();\r
+ *(_buffer + (unsigned)(_head) % _size) = *buffer++;\r
+ _head = (_head + 1) % _size;\r
+ write++;\r
+ _mutex->unlock();\r
+ _writeCondition->notify();\r
+ }\r
+ }\r
+ //std::cout << "Wrote " << write << " bytes to Fifo " << _name << "." << std::endl;\r
+ return write;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::size() const {\r
+ return (_size - 1);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::unused() const {\r
+ return (_size - 1) - used();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::used() const {\r
+ if (_head >= _tail) {\r
+ return _head - _tail;\r
+ }\r
+ return _head + _size - _tail;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+char* Fifo::getName() const {\r
+ return _name;\r
+}\r
+\r
+/**\r
+ * Test the implementation\r
+ */\r
+/*\r
+#include <iostream>\r
+void* producer(void *fifo)\r
+{\r
+ const char *str =\r
+ "Visit www.systemc.org and see what SystemC can do for you today!\n";\r
+\r
+ while (*str) {\r
+ //printf("%c", *str);\r
+ ((Fifo*)fifo)->write((void*)str++, 4);\r
+ }\r
+ printf("\nproducer returns.\n");\r
+ return 0;\r
+}\r
+\r
+void* consumer(void *fifo)\r
+{\r
+ char c;\r
+ while (c != '\n') {\r
+ ((Fifo*)fifo)->read(&c, 4);\r
+ std::cout << c << std::flush;\r
+\r
+ if (((Fifo*)fifo)->used() == 1)\r
+ std::cout << "<1>" << std::flush;\r
+ if (((Fifo*)fifo)->used() == 9)\r
+ std::cout << "<9>" << std::flush;\r
+ }\r
+ printf("\nconsumer returns.\n");\r
+ return 0;\r
+}\r
+\r
+\r
+int main() {\r
+ Fifo *fifo = new Fifo("fifo", 3);\r
+ pthread_t *producer_thread = new pthread_t;\r
+ pthread_t *consumer_thread = new pthread_t;\r
+\r
+ pthread_attr_t attributes;\r
+ pthread_attr_init(&attributes);\r
+ pthread_attr_setstacksize(&attributes, 131072);\r
+\r
+ if (pthread_create(consumer_thread, &attributes, consumer, fifo)) {\r
+ std::cout << "Error: Could not start consumer." << std::endl;\r
+ std::cout << "Exit." << std::endl;\r
+ exit(1);\r
+ }\r
+ pthread_attr_destroy(&attributes);\r
+\r
+ pthread_attr_init(&attributes);\r
+ pthread_attr_setstacksize(&attributes, 131072);\r
+ if (pthread_create(producer_thread, &attributes, producer, fifo)) {\r
+ std::cout << "Error: Could not start producer." << std::endl;\r
+ std::cout << "Exit." << std::endl;\r
+ exit(1);\r
+ }\r
+ pthread_attr_destroy(&attributes);\r
+\r
+\r
+ pthread_join(*consumer_thread, 0);\r
+ delete fifo;\r
+ return 0;\r
+}\r
+*/\r
--- /dev/null
+#ifndef _FIFO_H_\r
+#define _FIFO_H_\r
+\r
+#include <string.h>\r
+#include <stdio.h>\r
+#include "Mutex.h"\r
+#include "Condition.h"\r
+\r
+class Fifo {\r
+ public:\r
+ Fifo(char* name, unsigned size);\r
+ virtual ~Fifo();\r
+\r
+ virtual unsigned read(void *destination, unsigned len);\r
+ virtual unsigned write(const void *source, unsigned len);\r
+ virtual unsigned used() const;\r
+ virtual unsigned unused() const;\r
+ virtual unsigned size() const;\r
+ virtual char* getName() const;\r
+\r
+ protected:\r
+ char *_buffer;\r
+ unsigned _head;\r
+ unsigned _tail;\r
+ unsigned _size;\r
+ char *_name;\r
+ Mutex *_mutex;\r
+ Condition *_readCondition, *_writeCondition;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#include "Mutex.h"\r
+\r
+Mutex::Mutex() {\r
+ //std::cout << "Create Mutex." << std::endl;\r
+ _mutex = new pthread_mutex_t;\r
+ pthread_mutex_init(_mutex, NULL); //_mutexAttribute);\r
+\r
+ _localMutex = new pthread_mutex_t;\r
+ pthread_mutex_init(_localMutex, NULL);\r
+\r
+ _lockCondition = new pthread_cond_t;\r
+ pthread_cond_init(_lockCondition, NULL);\r
+}\r
+\r
+\r
+Mutex::~Mutex() {\r
+ //std::cout << "Delete Mutex." << std::endl;\r
+ pthread_mutex_destroy(_mutex);\r
+ delete _mutex;\r
+\r
+ pthread_mutex_destroy(_localMutex);\r
+ delete _localMutex;\r
+\r
+ pthread_cond_destroy(_lockCondition);\r
+ delete _lockCondition;\r
+ //std::cout << "Deleted Mutex." << std::endl;\r
+}\r
+\r
+\r
+int Mutex::trylock() {\r
+ int success = pthread_mutex_trylock(_mutex);\r
+ return success;\r
+}\r
+\r
+\r
+void Mutex::lock() {\r
+ pthread_mutex_lock(_mutex);\r
+}\r
+\r
+\r
+void Mutex::unlock() {\r
+ pthread_mutex_unlock(_mutex);\r
+}\r
+\r
+\r
+pthread_mutex_t *Mutex::getPThreadMutex() const {\r
+ return _mutex;\r
+}\r
--- /dev/null
+#ifndef _MUTEX_H_\r
+#define _MUTEX_H_\r
+\r
+#include <iostream>\r
+#include <pthread.h>\r
+\r
+class Mutex {\r
+ public:\r
+ Mutex();\r
+ virtual ~Mutex();\r
+ virtual void lock();\r
+ virtual void unlock();\r
+ virtual int trylock();\r
+ virtual pthread_mutex_t *getPThreadMutex() const;\r
+\r
+ protected:\r
+ pthread_mutex_t *_mutex;\r
+ pthread_mutex_t *_localMutex;\r
+ pthread_cond_t *_lockCondition;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#include "ProcessWrapper.h"\r
+#include "dolSupport.h"\r
+\r
+/**\r
+ *\r
+ */\r
+ProcessWrapper::ProcessWrapper(char* name) {\r
+ _name = new char[strlen(name) + 1];\r
+ strcpy(_name, name);\r
+\r
+ _isDetached = false;\r
+ for (int i = 0; i < 4; i++) {\r
+ _iteratorIndex[i] = getIndex(_name, "_", i);\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+ProcessWrapper::~ProcessWrapper() {\r
+ if (_name) {\r
+ delete _name;\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ProcessWrapper::initialize() {\r
+ _process.init(&_process);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+int ProcessWrapper::fire()\r
+{\r
+ return _process.fire(&_process);\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void ProcessWrapper::detach() {\r
+ _isDetached = true;\r
+}\r
+\r
+\r
+/**\r
+ * Gets an index of a string, where the index must be separated by\r
+ * a character specified in tokens.\r
+ * Returns -1, when an error occurs.\r
+ *\r
+ * Example:\r
+ * getIndex("name_1_2", "_", 0) will return 1.\r
+ * getIndex("name_1_2", "_", 1) will return 2.\r
+ *\r
+ * @param string string to parse\r
+ * @param tokens delimiter of indices\r
+ * @param indexNumber position of index (starting at 0)\r
+ */\r
+int ProcessWrapper::getIndex(const char* string, char* tokens,\r
+ int indexNumber) const {\r
+ char* string_copy;\r
+ char* token_pointer;\r
+ int index = 0;\r
+\r
+ string_copy = (char*) malloc(sizeof(char) * (strlen(string) + 1));\r
+ if (!string_copy) {\r
+ fprintf(stderr, "getIndex(): could not allocate memory.\n");\r
+ return -1;\r
+ }\r
+\r
+ strcpy(string_copy, string);\r
+\r
+ token_pointer = strtok(string_copy, tokens);\r
+ do {\r
+ token_pointer = strtok(NULL, tokens);\r
+ index++;\r
+ } while (index <= indexNumber && token_pointer != 0);\r
+\r
+ if (token_pointer) {\r
+ index = atoi(token_pointer);\r
+ free(string_copy);\r
+ return index;\r
+ }\r
+\r
+ return -1;\r
+}\r
+\r
+\r
+/**\r
+ * Get the index of this process.\r
+ * @param indexNumber position of index (starting at 0)\r
+ */\r
+int ProcessWrapper::getIndex(unsigned indexNumber) const {\r
+ if (indexNumber < 4) {\r
+ return _iteratorIndex[indexNumber];\r
+ }\r
+ return -1;\r
+}\r
+\r
+\r
+/**\r
+ * Get the name of this process.\r
+ */\r
+char* ProcessWrapper::getName() const {\r
+ return _name;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+#ifdef INCLUDE_PROFILER\r
+void ProcessWrapper::addToProfile(const char *event, void *port,\r
+ int length) {\r
+ if (profiler_output_file != NULL) {\r
+ fprintf(profiler_output_file, "%u %s %s %p %d\n",\r
+ profiler_event_counter++, _name, event, port,\r
+ length);\r
+\r
+ } else {\r
+ printf("profiler_output_file does not exist");\r
+ }\r
+}\r
+#endif\r
--- /dev/null
+#ifndef _PROCESSWRAPPER_H_\r
+#define _PROCESSWRAPPER_H_\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "dol.h"\r
+#include "Fifo.h"\r
+#include "WindowedFifo.h"\r
+\r
+#ifdef INCLUDE_PROFILER\r
+extern FILE *profiler_output_file;\r
+extern unsigned int profiler_event_counter;\r
+#endif\r
+\r
+class ProcessWrapper\r
+{\r
+ public:\r
+ ProcessWrapper(char* name);\r
+ virtual ~ProcessWrapper();\r
+ virtual void initialize();\r
+ virtual int fire();\r
+ virtual bool isDetached() { return _isDetached; }\r
+ virtual void detach();\r
+ virtual int getIndex(unsigned indexNumber) const;\r
+ virtual char* getName() const;\r
+\r
+#ifdef INCLUDE_PROFILER\r
+ virtual void addToProfile(const char *event, void *port,\r
+ int length);\r
+#endif\r
+\r
+#ifdef INCLUDE_TRACE\r
+ int start_line;\r
+ int end_line;\r
+ char channel_name[NAME_LENGTH];\r
+#endif\r
+\r
+#ifdef INCLUDE_PERFORMANCE\r
+ int start_line;\r
+ int end_line;\r
+ CURRENT_TIME start_time;\r
+ CURRENT_TIME end_time;\r
+#endif\r
+\r
+ protected:\r
+ char* _name;\r
+ DOLProcess _process;\r
+ bool _isDetached;\r
+ int _iteratorIndex[4];\r
+ virtual int getIndex(const char* string, char* tokens,\r
+ int indexNumber) const;\r
+};\r
+\r
+#endif\r
+\r
--- /dev/null
+#include "Scheduler.h"
+
+typedef struct {
+ Scheduler *scheduler;
+ ProcessWrapper *process;
+} ProcessArgs;
+
+
+void* runProcessWrapperWrapper(void* arg) {
+ ProcessArgs *args = (ProcessArgs*)arg;
+ (args->scheduler)->runProcessWrapper(args->process);
+ delete args;
+ return 0;
+}
+
+
+void *scheduleWrapper(void *arg) {
+ ((Scheduler*)arg)->schedule();
+ return 0;
+}
+
+
+Scheduler::Scheduler() {
+ //std::cout << "Create Scheduler." << std::endl;
+ _listsMutex = new Mutex();
+ _listsCondition = new Condition(_listsMutex);
+ _mapsMutex = new Mutex();
+ _mapsCondition = new Condition(_mapsMutex);
+ _processMap = new std::map<ProcessWrapper*, pthread_t* >();
+ _notificationEventMap = new std::map<ProcessWrapper*, Event* >();
+ _scheduleList = new std::list<ProcessWrapper* >();
+ _detachList = new std::list<ProcessWrapper* >();
+ _stopScheduler = false;
+ _allStarted = false;
+}
+
+
+Scheduler::~Scheduler() {
+ delete _listsCondition;
+ delete _listsMutex;
+ delete _mapsCondition;
+ delete _mapsMutex;
+ delete _processMap;
+ delete _notificationEventMap;
+ delete _scheduleList;
+ delete _detachList;
+}
+
+
+void Scheduler::registerProcess(ProcessWrapper *process) {
+ pthread_t *newThread = new pthread_t;
+ _processMap->insert(std::pair<ProcessWrapper*, pthread_t* >
+ (process, newThread));
+ Event *newNotificationEvent =
+ new Event("notificationEvent for " + std::string(process->getName()));
+ _notificationEventMap->insert(std::pair<ProcessWrapper*, Event* >
+ (process, newNotificationEvent));
+ process->initialize();
+}
+
+
+void Scheduler::run() {
+ _mapsMutex->lock();
+
+ pthread_t scheduleThread;
+ if (pthread_create(&scheduleThread, NULL, scheduleWrapper, this)) {
+ std::cout << "Error: Could not start scheduler thread."
+ << std::endl;
+ std::cout << "Exit." << std::endl;
+ exit(1);
+ }
+ std::map<ProcessWrapper*, pthread_t* >::iterator iterator;
+ for (iterator = _processMap->begin();
+ iterator != _processMap->end();
+ iterator++) {
+
+ pthread_t *thread = (*iterator).second;
+
+ pthread_attr_t attributes;
+ pthread_attr_init(&attributes);
+ pthread_attr_setstacksize(&attributes, 131072);
+
+ ProcessArgs *args = new ProcessArgs;
+ args->scheduler = this;
+ args->process = (*iterator).first;
+ //std::cout << "Starting process "
+ // << ((ProcessWrapper*)args->process)->getName()
+ // << "." << std::endl;
+ if (pthread_create(thread, &attributes, runProcessWrapperWrapper, args)) {
+ std::cout << "Error: Could not start thread for process "
+ << ((ProcessWrapper*)(args->process))->getName()
+ << "." << std::endl;
+ std::cout << "Exit." << std::endl;
+ exit(1);
+ }
+ pthread_attr_destroy(&attributes);
+
+ //std::cout << "Started process "
+ // << ((ProcessWrapper*)(args->process))->getName()
+ // << "." << std::endl;
+ }
+ _mapsMutex->unlock();
+
+ //std::cout << "Started all registered processes." << std::endl;
+ _allStarted = true;
+ _listsCondition->notify();
+ //std::cout << "Wait until scheduler has stopped." << std::endl;
+
+ //wait until all processes have been detached
+ pthread_join(scheduleThread, 0);
+
+ //std::cout << "Scheduler has stopped." << std::endl;
+}
+
+
+void Scheduler::runProcessWrapper(ProcessWrapper *process) {
+ Event *_notificationEvent = (*_notificationEventMap)[process];
+
+ while (!process->isDetached()) {
+ _listsMutex->lock();
+ _scheduleList->push_back(process);
+ _listsCondition->notify();
+ _listsMutex->unlock();
+ _notificationEvent->wait();
+ process->fire();
+ }
+
+ _listsMutex->lock();
+ _detachList->push_back(process);
+ _listsMutex->unlock();
+ _listsCondition->notify();
+}
+
+
+void Scheduler::detachProcess(ProcessWrapper *process) {
+ _mapsMutex->lock();
+ pthread_t *threadToKill = (*_processMap)[process];
+ pthread_join(*threadToKill, 0);
+ delete threadToKill;
+ _processMap->erase(process);
+
+ Event *notificationEventToKill = (*_notificationEventMap)[process];
+ delete notificationEventToKill;
+ _notificationEventMap->erase(process);
+
+ if (_processMap->empty()) {
+ //std::cout << "No processes left in process map. Terminate."
+ // << std::endl;
+ _stopScheduler = true;
+ }
+ _mapsMutex->unlock();
+}
+
+
+void Scheduler::schedule() {
+ _listsMutex->lock();
+
+ while(!_stopScheduler) {
+ _listsCondition->wait();
+
+ if (_allStarted) {
+ std::list<ProcessWrapper* >::iterator listIterator;
+ for (listIterator = _detachList->begin();
+ listIterator != _detachList->end();
+ listIterator++) {
+ ProcessWrapper *process = (*listIterator);
+ detachProcess(process);
+ //std::cout << "Scheduler detached process "
+ // << process->getName() << "." << std::endl;
+ }
+ _detachList->clear();
+
+ for (listIterator = _scheduleList->begin();
+ listIterator != _scheduleList->end();
+ listIterator++) {
+ ProcessWrapper *process = (*listIterator);
+ ((Event*)(*_notificationEventMap)[process])->notifyAfterWait();
+ }
+ _scheduleList->clear();
+ }
+ }
+
+ _listsMutex->unlock();
+ //std::cout << "Stopped scheduler." << std::endl;
+}
--- /dev/null
+#ifndef _SCHEDULER_H_
+#define _SCHEDULER_H_
+
+#include <iostream>
+#include <list>
+#include <map>
+#include "Event.h"
+#include "ProcessWrapper.h"
+
+class Scheduler
+{
+ public:
+ Scheduler();
+ virtual ~Scheduler();
+
+ void registerProcess(ProcessWrapper *process);
+ void run();
+ void runProcessWrapper(ProcessWrapper *process);
+ void detachProcess(ProcessWrapper *process);
+ void schedule();
+
+ protected:
+ Mutex *_listsMutex;
+ Condition *_listsCondition;
+ Mutex *_mapsMutex;
+ Condition *_mapsCondition;
+ std::map<ProcessWrapper*, pthread_t* > *_processMap;
+ std::map<ProcessWrapper*, Event* > *_notificationEventMap;
+ std::list<ProcessWrapper* > *_scheduleList;
+ std::list<ProcessWrapper* > *_detachList;
+ bool _stopScheduler;
+ bool _allStarted;
+};
+
+#endif
--- /dev/null
+#include "WindowedFifo.h"\r
+#include <string.h>\r
+\r
+/**\r
+ *\r
+ */\r
+WindowedFifo::WindowedFifo(char* name, unsigned size = 20) {\r
+ //std::cout << "Create WindowedFifo." << std::endl;\r
+ _size = size;\r
+ _buffer = new char[_size];\r
+ _head = 0;\r
+ _tail = 0;\r
+ _headRoom = 0;\r
+ _tailRoom = 0;\r
+ _use = 0;\r
+ //indicates whether Fifo is empty or full if _head == _tail\r
+ //_isFull = false;\r
+ _isHeadReserved = false;\r
+ _isTailReserved = false;\r
+ _name = new char[strlen(name) + 1];\r
+ strcpy(_name, name);\r
+ _mutex = new Mutex();\r
+ _readCondition = new Condition(_mutex);\r
+ _writeCondition = new Condition(_mutex);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+WindowedFifo::~WindowedFifo() {\r
+ //std::cout << "Delete WindowedFifo." << std::endl;\r
+ if (_buffer) {\r
+ delete _buffer;\r
+ }\r
+ if (_name) {\r
+ delete _name;\r
+ }\r
+ if (_readCondition) {\r
+ delete _readCondition;\r
+ }\r
+ if (_writeCondition) {\r
+ delete _writeCondition;\r
+ }\r
+ if (_mutex) {\r
+ delete _mutex;\r
+ }\r
+ _buffer = 0;\r
+ _head = 0;\r
+ _tail = 0;\r
+ _name = 0;\r
+ _use = 0;\r
+ _readCondition = 0;\r
+ _writeCondition = 0;\r
+ _mutex = 0;\r
+ //std::cout << "Deleted WindowedFifo." << std::endl;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::reserve(void** dest, unsigned len) {\r
+ char** destination = (char**)dest;\r
+ //std::cout << "Attempt to reserve " << len << " bytes." << std::endl;\r
+\r
+ //can only reserve once piece at a time\r
+ if (_isHeadReserved) {\r
+ *destination = 0;\r
+ return 0;\r
+ }\r
+\r
+ _mutex->lock();\r
+ while (unused() == 0) {\r
+ _readCondition->wait();\r
+ }\r
+\r
+ //reserve at most as much memory as still available in the buffer\r
+ unsigned write = (len <= _size - _use ? len : _size - _use);\r
+\r
+ if ( write > 0 ) {\r
+ //if wrap-around in buffer: return only buffer for the\r
+ //contiguous buffer space\r
+ if (_head + write > _size) {\r
+ write = _size - _head;\r
+ }\r
+\r
+ _headRoom = (_head + write) == _size? 0 : _head + write;\r
+ *destination = &(_buffer[_head]);\r
+ _isHeadReserved = true;\r
+\r
+ //the following comparison is unsafe in a multi-threaded\r
+ //environment and potentially leads to race-conditions\r
+ /*if (_headRoom == _tail) {\r
+ _isFull = true;\r
+ } else {\r
+ _isFull = false;\r
+ }*/\r
+ }\r
+ _writeReserve = write; \r
+ _mutex->unlock();\r
+\r
+ //std::cout << "Reserved " << write << " bytes." << std::endl;\r
+ return write;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void WindowedFifo::release() {\r
+ if (_isHeadReserved) {\r
+ //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl;\r
+ _head = _headRoom;\r
+ _use += _writeReserve;\r
+ _isHeadReserved = false;\r
+ _writeCondition->notify();\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::capture(void **dest, unsigned len) {\r
+ char** destination = (char**)dest;\r
+ //std::cout << "Attempt to capture " << len << " bytes." << std::endl;\r
+\r
+ if (_isTailReserved) {\r
+ //std::cout << "Only one attempt to capture allowed." << std::endl;\r
+ *destination = 0;\r
+ return 0;\r
+ }\r
+\r
+ _mutex->lock();\r
+ while (used() == 0) {\r
+ _writeCondition->wait();\r
+ }\r
+\r
+ //capture at most as much data as available in the buffer\r
+ unsigned read = (len <= _use ? len : _use);\r
+\r
+ if (read > 0) {\r
+ //if wrap-around in buffer: return only buffer for the\r
+ //contiguous buffer space\r
+ if (_tail + read> _size) {\r
+ read = _size - _tail;\r
+ }\r
+\r
+ _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read;\r
+ *destination = &(_buffer[_tail]);\r
+ _isTailReserved = true;\r
+ }\r
+ _readReserve = read; \r
+ _mutex->unlock();\r
+ //std::cout << "Captured " << read << " bytes." << std::endl;\r
+\r
+ return read;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void WindowedFifo::consume() {\r
+ _mutex->lock();\r
+ if (_isTailReserved) {\r
+ //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl;\r
+ _tail = _tailRoom;\r
+ //_isFull = false;\r
+ _use -= _readReserve;\r
+ _isTailReserved = false;\r
+ _readCondition->notify();\r
+ }\r
+ _mutex->unlock();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::size() const {\r
+ return _size;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::unused() const {\r
+ return _size - _use;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::used() const {\r
+ return _use;\r
+ /*if (_headRoom > _tail) {\r
+ return _headRoom - _tail;\r
+ } else if (_headRoom == _tail) {\r
+ if (_isFull == true) {\r
+ return _size;\r
+ } else {\r
+ return 0;\r
+ }\r
+ }\r
+ return _headRoom + _size - _tail;*/\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+char* WindowedFifo::getName() const {\r
+ return _name;\r
+}\r
+\r
+/**\r
+ * Test the implementation\r
+ */\r
+/*\r
+#include <iostream>\r
+#include <iomanip>\r
+#define LENGTH 10\r
+\r
+void* producer(void *fifo)\r
+{\r
+ WindowedFifo* wfifo = (WindowedFifo*)fifo;\r
+ for (int j = 0; j < LENGTH; j++) {\r
+ //std::cout << "write " << i << " to Fifo. ";\r
+ int *buf1;\r
+ int write = wfifo->reserve((void**)&buf1, sizeof(int));\r
+\r
+ if (write == sizeof(int)) {\r
+ *buf1 = j;\r
+ wfifo->release();\r
+ //std::cout << "used: " << std::setw(2) << wfifo->used()\r
+ // << ", unused: " << std::setw(2) << wfifo->unused()\r
+ // << ", size: " << std::setw(2) << wfifo->size()\r
+ // << std::endl;\r
+ } else {\r
+ std::cout << "Not successful: " << write << std::endl;\r
+ }\r
+ }\r
+ printf("producer returns.\n");\r
+ return 0;\r
+}\r
+\r
+void* consumer(void *fifo)\r
+{\r
+ WindowedFifo* wfifo = (WindowedFifo*)fifo;\r
+ for (int j = 0; j < LENGTH; j++) {\r
+ int* buf3;\r
+ int read = wfifo->capture((void**)&buf3, sizeof(int));\r
+ if (read == sizeof(int)) {\r
+ std::cout << "read " << (unsigned)*buf3 << " from WindowedFifo ";\r
+ std::cout << "used: " << std::setw(2) << wfifo->used()\r
+ << ", unused: " << std::setw(2) << wfifo->unused()\r
+ << ", size: " << std::setw(2) << wfifo->size()\r
+ << std::endl;\r
+ wfifo->consume();\r
+ } else {\r
+ std::cout << "Read nothing from WindowedFifo." << std::endl;\r
+ }\r
+ }\r
+ printf("consumer returns.\n");\r
+ return 0;\r
+}\r
+\r
+int main() {\r
+ WindowedFifo *wfifo = new WindowedFifo("fifo", 12);\r
+\r
+ int* buf1;\r
+ int* buf2;\r
+ wfifo->reserve((void**)&buf1, 8);\r
+ *buf1 = 10;\r
+ *(buf1 + 1) = 20;\r
+ wfifo->release();\r
+ wfifo->capture((void**)&buf2, 8);\r
+ std::cout << "read " << *buf2 << " " << *(buf2 + 1) << std::endl;\r
+ wfifo->consume();\r
+\r
+ pthread_t *producer_thread = new pthread_t;\r
+ pthread_t *consumer_thread = new pthread_t;\r
+\r
+ pthread_attr_t attributes;\r
+ pthread_attr_init(&attributes);\r
+ pthread_attr_setstacksize(&attributes, 131072);\r
+\r
+ if (pthread_create(consumer_thread, &attributes, consumer, wfifo)) {\r
+ std::cout << "Error: Could not start consumer." << std::endl;\r
+ std::cout << "Exit." << std::endl;\r
+ exit(1);\r
+ }\r
+ pthread_attr_destroy(&attributes);\r
+\r
+ pthread_attr_init(&attributes);\r
+ pthread_attr_setstacksize(&attributes, 131072);\r
+ if (pthread_create(producer_thread, &attributes, producer, wfifo)) {\r
+ std::cout << "Error: Could not start producer." << std::endl;\r
+ std::cout << "Exit." << std::endl;\r
+ exit(1);\r
+ }\r
+ pthread_attr_destroy(&attributes);\r
+\r
+\r
+ pthread_join(*consumer_thread, 0);\r
+ delete wfifo;\r
+ return 0;\r
+}\r
+*/\r
--- /dev/null
+#ifndef _WINDOWEDFIFO_H_\r
+#define _WINDOWEDFIFO_H_\r
+\r
+#include "Mutex.h"\r
+#include "Condition.h"\r
+\r
+class WindowedFifo {\r
+ public:\r
+ WindowedFifo(char* name, unsigned size);\r
+ virtual ~WindowedFifo();\r
+\r
+ virtual unsigned reserve(void** destination, unsigned len);\r
+ virtual void release();\r
+\r
+ virtual unsigned capture(void** destination, unsigned len);\r
+ virtual void consume();\r
+\r
+ virtual unsigned used() const;\r
+ virtual unsigned unused() const;\r
+ virtual unsigned size() const;\r
+ virtual char* getName() const;\r
+\r
+ protected:\r
+ char *_buffer;\r
+ unsigned _head;\r
+ unsigned _tail;\r
+ unsigned _headRoom;\r
+ unsigned _tailRoom;\r
+ unsigned _size;\r
+ unsigned _use;\r
+ unsigned _writeReserve;
+ unsigned _readReserve;
+ //bool _isFull;\r
+ bool _isHeadReserved;\r
+ bool _isTailReserved;\r
+ char *_name;\r
+ Mutex *_mutex;\r
+ Condition *_readCondition, *_writeCondition;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#ifndef DOL_H
+#define DOL_H
+
+/************************************************************************
+ * do not add code to this header
+ ************************************************************************/
+
+/**
+ * Define the DOL process handler scheme.
+ * - Local variables are defined in structure LocalState. Local
+ * variables may vary from different processes.
+ * - The ProcessInit function pointer points to a function which
+ * initializes a process.
+ * - The ProcessFire function pointer points to a function which
+ * performs the actual computation. The communication between
+ * processes is inside the ProcessFire function.
+ * - The WPTR is a placeholder for callback. One can just
+ * leave it blank.
+ */
+
+//structure for local memory of process
+typedef struct _local_states *LocalState;
+
+//additional behavioral functions could be declared here
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+//process handler
+struct _process;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr; //placeholder for wrapper instance
+} DOLProcess;
+
+#endif
--- /dev/null
+#include "dolSupport.h"\r
+#include "ProcessWrapper.h"\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned write(void *port, void *buf, unsigned len, DOLProcess *process)\r
+{\r
+ Fifo *fifo = static_cast<Fifo *>(port);\r
+ char *str = static_cast<char*>(buf);\r
+ fifo->write((void*)str, len);\r
+ return len;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned read(void *port, void *buf, unsigned len, DOLProcess *process) {\r
+ Fifo *fifo = static_cast<Fifo *>(port);\r
+ char *str = static_cast<char*>(buf);\r
+ fifo->read((void*)str, len);\r
+ return len;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+int wtest(void *port, unsigned len, DOLProcess *process) {\r
+ Fifo *fifo = static_cast<Fifo *>(port);\r
+ return (fifo->unused() >= len) ? 1 : 0;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+int rtest(void *port, unsigned len, DOLProcess *process) {\r
+ Fifo *fifo = static_cast<Fifo *>(port);\r
+ return (fifo->used() >= len) ? 1 : 0;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned reserve(void* fifo, void** destination, unsigned len, DOLProcess* p) {\r
+ return ((WindowedFifo*)fifo)->reserve(destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void release(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*)fifo)->release();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned capture(void* fifo, void** destination, unsigned len, DOLProcess* p) {\r
+ return ((WindowedFifo*)fifo)->capture(destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void consume(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*)fifo)->consume();\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void DOL_detach(DOLProcess* p) {\r
+ static_cast<ProcessWrapper *>(p->wptr)->detach();\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0) {\r
+ *port = (void**)((void**)base)[index0];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1) {\r
+ *port = (void**)((void**)base)[index0 * range1 + index1];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2) {\r
+ *port = (void**)((void**)base)[index0 * range1 * range2\r
+ + index1 * range2 + index2];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2,\r
+ int index3, int range3) {\r
+ *port = (void**)((void**)base)[index0 * range1 * range2 * range3\r
+ + index1 * range2 * range3\r
+ + index2 * range3\r
+ + index3];\r
+}\r
--- /dev/null
+#ifndef DOLSUPPORT_H\r
+#define DOLSUPPORT_H\r
+\r
+#include "dol.h"\r
+#include "Fifo.h"\r
+#ifdef INCLUDE_PERFORMANCE\r
+#include "Performance_Extraction.h"\r
+#elif INCLUDE_TRACE\r
+#include "functional_trace.h"\r
+#endif\r
+\r
+#ifdef INCLUDE_PERFORMANCE\r
+#define DOL_write(port, buf, len, process) {\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line = __LINE__;\\r
+ get_current_time(&((static_cast<ProcessWrapper *>(p->wptr))->\\r
+ end_time));\\r
+ performance_extraction.add_computation_performance(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(),\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line,\\r
+ &((static_cast<ProcessWrapper *>(p->wptr))->start_time),\\r
+ &((static_cast<ProcessWrapper *>(p->wptr))->end_time));\\r
+ write(port, buf, len, process);\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line = __LINE__;\\r
+ get_current_time(&((static_cast<ProcessWrapper *>(p->wptr))->\\r
+ start_time)); }\r
+#define DOL_read(port, buf, len, process) {\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line = __LINE__;\\r
+ get_current_time(&((static_cast<ProcessWrapper *>(p->wptr))->\\r
+ end_time));\\r
+ performance_extraction.add_computation_performance(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(),\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line,\\r
+ &((static_cast<ProcessWrapper *>(p->wptr))->start_time),\\r
+ &((static_cast<ProcessWrapper *>(p->wptr))->end_time));\\r
+ read(port, buf, len, process);\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line = __LINE__;\\r
+ get_current_time(&((static_cast<ProcessWrapper *>(p->wptr))->\\r
+ start_time)); }\r
+#elif INCLUDE_TRACE\r
+#define DOL_write(port, buf, len, process) {\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line = __LINE__;\\r
+ dol_functional_trace.create_computation_event(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(),\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line);\\r
+ write(port, buf, len, process);\\r
+ dol_functional_trace.create_write_event(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(), len,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->channel_name);\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line = __LINE__; }\r
+#define DOL_read(port, buf, len, process) {\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line = __LINE__;\\r
+ dol_functional_trace.create_computation_event(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(),\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line);\\r
+ read(port, buf, len, process);\\r
+ dol_functional_trace.create_read_event(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(), len,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->channel_name);\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line = __LINE__; }\r
+#else\r
+ #define DOL_write(port, buf, len, process) \\r
+ write(port, buf, len, process)\r
+ #define DOL_read(port, buf, len, process) \\r
+ read(port, buf, len, process)\r
+#endif\r
+\r
+#define DOL_reserve(port, buf, size, process) \\r
+ reserve(port, (void**)buf, size, process);\r
+\r
+#define DOL_release(port, process) \\r
+ release(port, process);\r
+\r
+#define DOL_capture(port, buf, size, process) \\r
+ capture(port, (void**)buf, size, process);\r
+\r
+#define DOL_consume(port, process) \\r
+ consume(port, process);\r
+\r
+#define DOL_wtest(port, len, process) wtest(port, len, process)\r
+\r
+#define DOL_rtest(port, len, process) rtest(port, len, process)\r
+\r
+void DOL_detach(DOLProcess* p);\r
+\r
+//fifo access functions\r
+unsigned write(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+unsigned read(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+int wtest(void *port, unsigned len, DOLProcess *process);\r
+int rtest(void *port, unsigned len, DOLProcess *process);\r
+\r
+//windowed fifo access functions\r
+unsigned reserve(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+void release(void* fifo, DOLProcess* p);\r
+unsigned capture(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+void consume(void* fifo, DOLProcess* p);\r
+\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2,\r
+ int index3, int range3);\r
+\r
+#define GETINDEX(dimension) \\r
+ static_cast<ProcessWrapper *>(p->wptr)->getIndex(dimension)\r
+\r
+/**\r
+ * macro to create a variable to store a port name\r
+ *\r
+ * @param name name of the variable\r
+ */\r
+#define CREATEPORTVAR(name) Fifo *name\r
+\r
+/**\r
+ * Create the port name of an iterated port based on its basename and the\r
+ * given indices.\r
+ *\r
+ * @param port buffer where the result is stored (created using\r
+ * CREATEPORTVAR)\r
+ * @param base basename of the port\r
+ * @param number_of_indices number of dimensions of the port\r
+ * @param index_range_pairs index and range values for each dimension\r
+ */\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+ createPort((void**)(&port), base, number_of_indices, index_range_pairs)\r
+\r
+#endif\r
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Code generator for functional simulation using threads for execution (no SystemC required).
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: Visitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor;
+
+/**
+ * This class is a marker Class, to indicate that derived classes are all
+ * visitor.
+ */
+public interface Visitor {
+}
--- /dev/null
+/* $Id: CbeBuildFileVisitor.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.visitor.cbe;\r
+\r
+import java.io.FileOutputStream;\r
+import java.io.OutputStream;\r
+import java.io.PrintStream;\r
+import java.util.Vector;\r
+\r
+import dol.datamodel.pn.Process;\r
+import dol.datamodel.pn.ProcessNetwork;\r
+import dol.visitor.PNVisitor;\r
+\r
+/**\r
+ * This class is a class for a visitor that is used to generate the build\r
+ * file for the application on the CBE (i.e. a bash file for the CBE)\r
+ *\r
+ * @author lschor, 2008-10-30\r
+ *\r
+ * Revision:\r
+ * 2008-10-30: Updated the file for the CBE\r
+ * 2008-11-08: Add double buffering\r
+ */\r
+public class CbeBuildFileVisitor extends PNVisitor {\r
+\r
+ /**\r
+ * Constructor.\r
+ *\r
+ * @param dir path of the Makefile\r
+ */\r
+ public CbeBuildFileVisitor(String dir) {\r
+ _dir = dir;\r
+ }\r
+\r
+ /**\r
+ * Create a Makefile for the given process network.\r
+ *\r
+ * @param pn process network\r
+ */\r
+ public void visitComponent(ProcessNetwork pn) {\r
+ try {\r
+ String filename = _dir + _delimiter + "pncbe.sh";\r
+ OutputStream file = new FileOutputStream(filename);\r
+ PrintStream ps = new PrintStream(file);\r
+\r
+ // General information / notes and commands\r
+ ps.println("#!/bin/bash");\r
+ ps.println("clear");\r
+ ps.println();\r
+ ps.println("# Bash file to run a DOL application on the CBE");\r
+ ps.println("# Start the CBE-Simulator and enter the "\r
+ + "following commands: ");\r
+ ps.println("# callthru source <Absolute path to the folder "\r
+ + "of this file>/pncbe.sh > pncbe.sh");\r
+ ps.println("# for example: callthru source /opt/cell/sdk/src/"\r
+ + "tutorial/pn_test/pncbe.sh > pncbe.sh");\r
+ ps.println("# chmod +x pncbe.sh");\r
+ ps.println();\r
+ ps.println("# To run the DOL application, use the following "\r
+ + "command: ");\r
+ ps.println("# ./pncbe.sh");\r
+ ps.println();\r
+ ps.println("# Folder in which the application is stored");\r
+ ps.println("FOLDER=/opt/cell/sdk/src/tutorial/pn_test");\r
+ ps.println();\r
+\r
+ // Go through each process and copy its data to the Cell\r
+ String subdirectory = "";\r
+ String applicationName = "";\r
+ Vector<String> pList = new Vector<String>();\r
+\r
+ for (Process process : pn.getProcessList()) {\r
+ String basename = process.getBasename();\r
+ if (!pList.contains(basename)\r
+ && process.getNumOfInports() > 0\r
+ && process.getNumOfOutports() > 0) {\r
+ subdirectory = "spu_" + basename;\r
+ applicationName = subdirectory + "/spu_"\r
+ + basename + "_wrapper";\r
+\r
+ ps.println("# " + basename);\r
+ ps.println("if [ ! -d " + subdirectory + " ]; then");\r
+ ps.println("\tmkdir " + subdirectory);\r
+ ps.println("fi;");\r
+ ps.println("callthru source $FOLDER/"\r
+ + applicationName + " > " + applicationName);\r
+ ps.println("chmod +x " + applicationName);\r
+ ps.println();\r
+ pList.add(basename);\r
+ }\r
+ }\r
+\r
+ // Load also the main application to the CBE\r
+ ps.println("# Main program");\r
+ ps.println("callthru source $FOLDER/ppu_main > ppu_main");\r
+ ps.println("chmod +x ppu_main");\r
+ ps.println();\r
+\r
+ // Run the main program\r
+ ps.println("# run the main program");\r
+ ps.println("./ppu_main");\r
+ } catch (Exception e) {\r
+ System.out.println("CbeMakefileVisitor: exception occured: "\r
+ + e.getMessage());\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ protected String _dir = null;\r
+}\r
--- /dev/null
+/* $Id: CbeConstantVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.cbe;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a constant file
+ *
+ * @author lschor, 2008-11-08
+ *
+ * Revision:
+ * 2008-11-08: Created
+ */
+public class CbeConstantVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of this file
+ */
+ public CbeConstantVisitor(String dir, HashMap<Port, Integer> portMap) {
+ _dir = dir;
+ _portMap = portMap;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ _ui = UserInterface.getInstance();
+ String filename = _dir + _delimiter + "lib" + _delimiter
+ + "constant.h";
+ OutputStream file = new FileOutputStream(filename);
+ _mainPS = new CodePrintStream(file);
+
+ int numSpes = 0;
+
+ for (Process p : x.getProcessList())
+ {
+ if (p.getNumOfInports() > 0 && p.getNumOfOutports() > 0)
+ numSpes++;
+ }
+
+ //create header section
+ _mainPS.println("// ========================");
+ _mainPS.println("// constant.c file");
+ _mainPS.println("// ========================");
+
+ //includes
+ _mainPS.println("#include <stdio.h>");
+
+ //define the number of FIFO queues and the number of processes
+ _mainPS.println("#ifndef _CONSTANT_H_");
+ _mainPS.println("#define _CONSTANT_H_");
+ _mainPS.println("");
+ _mainPS.println("#define NUM_PROCS "
+ + x.getProcessList().size());
+ _mainPS.println("#define NUM_SPES " + numSpes);
+ _mainPS.println("#define NUM_FIFO "
+ + x.getChannelList().size());
+ _mainPS.println("");
+ _mainPS.println("#endif // _CONSTANT_H_ ");
+ _mainPS.println("");
+ }
+ catch (Exception e) {
+ System.out.println("CbeModuleVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param x process that needs to be processed
+ */
+ public void visitComponent(Process x) {
+ }
+
+ /**
+ *
+ * @param x channel that needs to be processed
+ */
+ public void visitComponent(Channel x) {
+ }
+
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected HashMap<Port, Integer> _portMap;
+}
--- /dev/null
+/* $Id: CbeMakefileVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.cbe;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate a CBE
+ * package Makefile.
+ */
+public class CbeMakefileVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of the Makefile
+ */
+ public CbeMakefileVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ * Create a Makefile for the given process network.
+ *
+ * @param pn process network
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ String filename = _dir + _delimiter + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ ps.println("##############################################");
+ ps.println("# Main Makefile for DOL application on the CBE");
+ ps.println("##############################################");
+ ps.println();
+ ps.println("# Subdirectories");
+
+ String subdirectories = "";
+ Vector<String> pList = new Vector<String>();
+ for (Process process : pn.getProcessList()) {
+ String basename = process.getBasename();
+ if (!pList.contains(basename)) {
+ if (process.getNumOfInports() > 0
+ && process.getNumOfOutports() > 0) {
+ subdirectories += "spu_" + basename + " ";
+ }
+ pList.add(basename);
+ }
+ }
+ pList.clear();
+
+ String linkList = "";
+ String srcList = "";
+ for (Process process : pn.getProcessList()) {
+ String basename = process.getBasename();
+ if (!pList.contains(basename)) {
+ if (!(process.getNumOfInports() > 0
+ && process.getNumOfOutports() > 0)) {
+ linkList += "ppu_" + basename + "/ppu_" + basename
+ + ".o ";
+ srcList += "$(wildcard ppu_" + basename
+ + "/*.c) ";
+
+ }
+ pList.add(basename);
+ }
+ }
+ pList.clear();
+
+ ps.println("DIRS\t := " + subdirectories);
+ ps.println("");
+
+ ps.println("# General definitions:");
+ ps.println("CC = ppu-g++");
+ ps.println("CCFLAGS = -ftree-vectorize -O3 -maltivec "
+ + "-funroll-loops -mabi=altivec -mcpu=cell");
+ ps.println("COMPILE = $(CC) $(CCFLAGS) -c");
+ ps.println("LINK = $(CC) -lspe2 -lpthread");
+ ps.println("CBE_INCLUDE = /opt/cell/sdk/src/include/ppu");
+ ps.println("LIB_INC = -I lib -I . -I $(CBE_INCLUDE)");
+ ps.println("RM = rm");
+ ps.println("ECHO = echo");
+ ps.println("EXE = ppu_main");
+ ps.println("");
+ ps.println("src := $(wildcard lib/*.c) $(wildcard *.c)");
+ ps.println("srcAll := $(wildcard lib/*.c) "
+ + "$(wildcard lib/*.c) " + srcList);
+ ps.println("obj = $(src:.c=.o)");
+ ps.println("");
+ ps.println("$(EXE): $(obj) $(srcAll)");
+ ps.println("\tfor d in $(DIRS); do (cd $$d; $(MAKE) ); done");
+
+ for (Process process : pn.getProcessList()) {
+ String basename = process.getBasename();
+ if (!pList.contains(basename)) {
+ if (!(process.getNumOfInports() > 0
+ && process.getNumOfOutports() > 0)) {
+ ps.println("\tcd ppu_" + basename
+ + "; $(COMPILE) -o ppu_" + basename
+ + ".o ppu_" + basename
+ + "_wrapper.c -I .. -I ../lib;");
+ }
+ pList.add(basename);
+ }
+ }
+ pList.clear();
+
+ ps.println("\t$(LINK) -o $(EXE) " + linkList + " $(obj)");
+ ps.println("");
+ ps.println("%.o :");
+ ps.println("\t$(COMPILE) -o $(*D)/$(*F).o $(*D)/$(*F).c "
+ + "$(LIB_INC)");
+ ps.println("");
+ ps.println("clean:");
+ ps.println("\tfor d in $(DIRS); do (cd $$d; $(MAKE) clean );"
+ + " done");
+ ps.println("\trm $(obj) ");
+
+ for (Process process : pn.getProcessList()) {
+ String basename = process.getBasename();
+ if (!pList.contains(basename)) {
+ if (!(process.getNumOfInports() > 0
+ && process.getNumOfOutports() > 0))
+ {
+ ps.println("\trm ppu_" + basename + "/ppu_"
+ + basename + ".o");
+ }
+ pList.add(basename);
+ }
+ }
+ pList.clear();
+
+ ps.println("\trm ppu_main");
+ ps.println("");
+
+ } catch (Exception e) {
+ System.out.println("CbeMakefileVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+}
--- /dev/null
+/* $Id: CbeModuleVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.cbe;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Vector;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * the main program.
+ *
+ * @author lschor, 2008-10-30
+ *
+ * Revision:
+ * 2008-10-30: Updated the file for the CBE
+ * 2008-11-08: Add double buffering
+ * 2008-11-16: Add new fifo implementation and defines for measurement
+ * 2008-11-21: Sink/Source do not run on the SPE, but on the PPE (as Linux
+ * thread)
+ */
+public class CbeModuleVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of this file
+ */
+ public CbeModuleVisitor(String dir, HashMap<Port, Integer> portMap) {
+ _dir = dir;
+ _portMap = portMap;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ _ui = UserInterface.getInstance();
+ String filename = _dir + _delimiter + "ppu_main.c";
+ OutputStream file = new FileOutputStream(filename);
+ _mainPS = new CodePrintStream(file);
+
+ //create header section
+ _mainPS.println("// ========================");
+ _mainPS.println("// ppu_main.c file");
+ _mainPS.println("// ========================");
+ _mainPS.println("");
+
+ // Includes
+ _mainPS.println("#include \"ppu_main.h\"");
+ _mainPS.println("");
+
+ _mainPS.println("");
+ _mainPS.println("// include main function for a workloop");
+ _mainPS.println("#include \"ppu_main_workloop.h\"");
+ _mainPS.println("");
+
+ // Function to create and run one SPE thread
+ _mainPS.println("// create and run one SPE thread");
+ _mainPS.println("void *spu_pthread(void *arg) {");
+ _mainPS.println("\t spu_data_t *datp = (spu_data_t *)arg;");
+ _mainPS.println("\t uint32_t entry = SPE_DEFAULT_ENTRY;");
+ _mainPS.println("\t printf(\")PPE: spe thread starts\\n\");");
+ _mainPS.println("\t if (spe_context_run(datp->spe_ctx, "
+ + "&entry, 0, datp->argp, NULL, NULL) < 0) {");
+ _mainPS.println("\t\t perror (\"Failed running context\"); "
+ + "exit (1);");
+ _mainPS.println("\t}");
+ _mainPS.println("\t printf(\")PPE: spe thread stops\\n\");");
+ _mainPS.println("\t pthread_exit(NULL);");
+ _mainPS.println("}");
+ _mainPS.println("");
+
+ // Declaration of the Header function for the PPE-Wrappers
+ Vector<String> processList = new Vector<String>();
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!processList.contains(basename)) {
+ processList.add(basename);
+ if (!(p.getNumOfInports() > 0
+ && p.getNumOfOutports() > 0))
+ _mainPS.println("void *" + basename
+ + "_wrapper( void *ptr );");
+ }
+ }
+ _mainPS.println();
+
+ // Create the port_id and the port_queue_id arrays to send
+ // over the DMA
+ for (Process process : x.getProcessList()) {
+ String processName = process.getName();
+ _mainPS.println("volatile uint32_t "+ processName
+ + "_port_id["
+ + roundDMA(process.getPortList().size())
+ + "] __attribute__ ((aligned(16))); ");
+ _mainPS.println("volatile uint32_t " + processName
+ + "_port_queue_id["
+ + roundDMA(process.getPortList().size())
+ + "] __attribute__ ((aligned(16)));");
+ _mainPS.println("volatile char " + processName
+ + "_name[256] __attribute__ ((aligned(16)));");
+ }
+ _mainPS.println();
+
+ // Create the main function
+ _mainPS.println("int main()");
+ _mainPS.println("{");
+
+ // For Measure
+ _mainPS.println("#ifdef MEASURE_APPLICATION");
+ _mainPS.println("\tstruct timeval t_ppe_start, t_ppe_end;");
+ _mainPS.println("\tgettimeofday(&t_ppe_start,NULL);");
+ _mainPS.println("#endif");
+ _mainPS.println();
+
+ _mainPS.println("#ifdef MEASURE_SET_UP_SPE_THREAD");
+ _mainPS.println("\tstruct timeval t_ppe_setup_start, "
+ + "t_ppe_setup_end;");
+ _mainPS.println("\tgettimeofday(&t_ppe_setup_start,NULL);");
+ _mainPS.println("#endif");
+ _mainPS.println();
+
+ // List with all process to be open
+ _mainPS.println("\tchar spe_names[NUM_SPES][60] = {");
+ int count = 0;
+ for (Process process : x.getProcessList()) {
+ if (process.getNumOfInports() > 0
+ && process.getNumOfOutports() > 0) {
+ count++;
+ String processName = process.getBasename();
+ _mainPS.println("\t\t\"spu_" + processName + "/spu_"
+ + processName + "_wrapper\""
+ + (count == x.getProcessList().size()
+ ? "" : ", ") );
+ }
+ }
+ _mainPS.println("\t};");
+ _mainPS.println();
+ _mainPS.println("\t// Initialize the fifo, we use");
+ _mainPS.println("\tint j; ");
+ _mainPS.println("\tfor (j = 0; j < NUM_FIFO; j++)");
+ _mainPS.println("\t{");
+ _mainPS.println("\t\tlocBuf[j] = "
+ + "(char*)malloc(MAXELEMENT * sizeof(char));");
+ _mainPS.println("\t\tlocBufCount[j] = 0;");
+ _mainPS.println("\t\tlocBufStart[j] = 0;");
+ _mainPS.println("\t\tpthread_mutex_init(&(mutex[j]), NULL);");
+ _mainPS.println("\t}");
+
+ //connect ports to channels
+ HashMap<Channel, Integer> channel_map =
+ new HashMap<Channel, Integer>();
+
+ int j = 0;
+ for (Channel c : x.getChannelList()) {
+ channel_map.put(c, j++);
+ }
+
+ // Init the SPE control structure
+ _mainPS.println("\t//Initiate SPEs control structure");
+ _mainPS.println("\tint num = 0; ");
+ _mainPS.println("\tfor( num=0; num<NUM_SPES; num++){");
+ _mainPS.println("\t\tdata[num].argp = (void *)&(ctx[num]);");
+ _mainPS.println("\t}");
+ _mainPS.println();
+
+ // Add to each process the ports and the queues
+ _mainPS.println("\t //Add to each process the ports and the "
+ + "queues");
+ j = 0;
+ for (Process process : x.getProcessList()) {
+ String processName = process.getName();
+ int i = 0;
+ for (Port port : process.getPortList()) {
+ Channel c = (Channel)(port.getPeerResource());
+
+ _mainPS.println("\t" + processName + "_port_id["
+ + i + "] = "
+ + _portMap.get(port) + ";");
+ _mainPS.println("\t" + processName + "_port_queue_id["
+ + i + "] = "
+ + channel_map.get(c) + ";");
+ i++;
+ }
+
+ // Normal process
+ if (process.getNumOfInports() > 0
+ && process.getNumOfOutports() > 0) {
+ _mainPS.println("\tctx[" + j + "]"
+ + ".port_id = (uint64_t)"
+ + processName + "_port_id;");
+ _mainPS.println("\tctx[" + j + "]"
+ + ".port_queue_id = (uint64_t)"
+ + processName + "_port_queue_id;");
+ _mainPS.println("\tctx[" + j + "]"
+ + ".number_of_ports = " + i + ";");
+ _mainPS.println("\tctx[" + j + "]"
+ + ".is_detached = 0;");
+ _mainPS.println("\tstrcpy((char *)" + processName
+ + "_name, " + "\""
+ + processName + "\");");
+ _mainPS.println("\tctx[" + j + "]"
+ + ".processName = (uint64_t) " + processName
+ + "_name;");
+ _mainPS.println("\tctx[" + j + "]"
+ + ".processNameLen = ((strlen((char *)"
+ + processName + "_name) + 15) & ~15);");
+ _mainPS.println();
+ j++;
+ }
+ // Process is Sink or source
+ else {
+ _mainPS.println("\tProcessWrapper *"
+ + process.getName()
+ + "_Process_Wrapper = (ProcessWrapper*)"
+ + "malloc(sizeof(ProcessWrapper)); ");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->port_id = " + processName
+ + "_port_id;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->port_queue_id = "
+ + processName + "_port_queue_id;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->number_of_ports = "
+ + i + ";");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->is_detached = 0;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->name = (char*)malloc("
+ + "strlen(\"" + processName + "\"));");
+ _mainPS.println("\tstrcpy(" + process.getName()
+ + "_Process_Wrapper->name, \"" + processName
+ + "\");");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->locBuf = locBuf;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->MAXELEMENT = "
+ + "MAXELEMENT;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->locBufCount = "
+ + "locBufCount;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->locBufStart = "
+ + "locBufStart;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->processFinished = "
+ + "&processFinished;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->mutex = mutex;");
+ _mainPS.println("\t" + process.getName()
+ + "_Process_Wrapper->mutexProcessNr = "
+ + "&mutexProcessNr;");
+ _mainPS.println();
+ }
+ }
+
+ _mainPS.println("\t// Loop on all SPEs and for each perform "
+ + "three steps:");
+ _mainPS.println("\t// - create SPE context");
+ _mainPS.println("\t// - open images of SPE programs into main "
+ + "storage");
+ _mainPS.println("\t// <spe_names> variable store the "
+ + "executable name");
+ _mainPS.println("\t// - Load SPEs objects into SPE context "
+ + "local store");
+ _mainPS.println("\tfor( num=0; num<NUM_SPES; num++){");
+ _mainPS.println("\t\tif ((data[num].spe_ctx = "
+ + "spe_context_create(0, NULL)) == NULL) {");
+ _mainPS.println("\t\t\tperror(\"Failed creating context\"); "
+ + "exit(1);");
+ _mainPS.println("\t\t}");
+ _mainPS.println("\t\tif (!(program[num] = spe_image_open("
+ + "&spe_names[num][0]))) {");
+ _mainPS.println("\t\t\t perror(\"Fail opening image\"); "
+ + "exit(1);");
+ _mainPS.println("\t\t}");
+ _mainPS.println("\t\tif (spe_program_load(data[num].spe_ctx, "
+ + "program[num])) {");
+ _mainPS.println("\t\t\tperror(\"Failed loading program\"); "
+ + "exit(1);");
+ _mainPS.println("\t\t} ");
+ _mainPS.println("\t}");
+ _mainPS.println("");
+
+ _mainPS.println("\t// create PPE pthreads");
+ for (Process process : x.getProcessList()) {
+ if (!(process.getNumOfInports() > 0
+ && process.getNumOfOutports() > 0)) {
+ _mainPS.println("\tpthread_t thread_"
+ + process.getName() + ";");
+ _mainPS.println("\tpthread_create( &thread_"
+ + process.getName() + ", NULL, "
+ + process.getBasename() + "_wrapper, "
+ + process.getName() + "_Process_Wrapper);");
+ }
+ }
+ _mainPS.println("\t");
+
+ _mainPS.println("\t// create SPE pthreads");
+ _mainPS.println("\tfor( num=0; num<NUM_SPES; num++){");
+ _mainPS.println("\t\tif(pthread_create(&data[num].pthread, "
+ + "NULL, &spu_pthread, &data[num])){");
+ _mainPS.println("\t\t\tperror(\"Failed creating thread\"); "
+ + "exit(1);");
+ _mainPS.println("\t\t}");
+ _mainPS.println("\t}");
+
+ _mainPS.println();
+ _mainPS.println("#ifdef MEASURE_SET_UP_SPE_THREAD");
+ _mainPS.println("\tgettimeofday(&t_ppe_setup_end, NULL);");
+ _mainPS.println("\tprintf(\"PPE_SETUP;%f\\n\", "
+ + "(t_ppe_setup_end.tv_sec "
+ + "- t_ppe_setup_start.tv_sec) + 0.000001 "
+ + "* (t_ppe_setup_end.tv_usec "
+ + "- t_ppe_setup_start.tv_usec));");
+ _mainPS.println("#endif");
+ _mainPS.println();
+
+ _mainPS.println("\t//Start the main loop");
+ _mainPS.println("\tworkloop();");
+ _mainPS.println("");
+
+ _mainPS.println("\t// Loop on all SPEs and for each perform "
+ + "two steps:");
+ _mainPS.println("\t// - wait for all the SPE pthread to "
+ + "complete");
+ _mainPS.println("\t// - destroy the SPE contexts");
+ _mainPS.println("\tfor( num=0; num<NUM_SPES; num++){");
+ _mainPS.println("\t\tif(pthread_join(data[num].pthread, "
+ + "NULL)) {");
+ _mainPS.println("\t\t\tperror(\"Failed joining thread\"); "
+ + "exit(1);");
+ _mainPS.println("\t\t}");
+ _mainPS.println("\t\t");
+ _mainPS.println("\t\tif (spe_context_destroy("
+ + "data[num].spe_ctx)) {");
+ _mainPS.println("\t\t\tperror(\"Failed "
+ + "spe_context_destroy\"); exit(1);");
+ _mainPS.println("\t\t}");
+ _mainPS.println("\t}");
+ _mainPS.println("\tprintf(\")PPE:) Complete running "
+ + "all SPEs\\n\");");
+ _mainPS.println("");
+ _mainPS.println("\tfor (j = 0; j < NUM_FIFO; j++)");
+ _mainPS.println("\t{");
+ _mainPS.println("\t\tfree(locBuf[j]);");
+ _mainPS.println("\t\tpthread_mutex_destroy (&(mutex[j]));");
+ _mainPS.println("\t}");
+ _mainPS.println("");
+ _mainPS.println("#ifdef MEASURE_APPLICATION");
+ _mainPS.println("\tgettimeofday(&t_ppe_end, NULL);");
+ _mainPS.println("\tprintf(\"PPE;%f\\n\",(t_ppe_end.tv_sec "
+ + "- t_ppe_start.tv_sec) + 0.000001 "
+ + "* (t_ppe_end.tv_usec - t_ppe_start.tv_usec));");
+ _mainPS.println("#endif");
+ _mainPS.println("");
+ _mainPS.println("\treturn (0);");
+ _mainPS.println("}");
+ }
+ catch (Exception e) {
+ System.out.println("CbeDBModuleVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param x process that needs to be processed
+ */
+ public void visitComponent(Process x) {
+ }
+
+ /**
+ *
+ * @param x channel that needs to be processed
+ */
+ public void visitComponent(Channel x) {
+ }
+
+ /**
+ * Round the parameter to the next DMA-number up.
+ * Example: 23 gives 32.
+ * @param number number to round up
+ * @return next DMA-number
+ */
+ protected int roundDMA(int number) {
+ if (number > 16) {
+ return number + 16 - (number % 16);
+ } else if (number > 8) {
+ return 16;
+ } else if (number > 4) {
+ return 8;
+ } else if (number > 2) {
+ return 4;
+ } else if (number > 1) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected HashMap<Port, Integer> _portMap;
+}
--- /dev/null
+/* $Id: CbeProcessVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.cbe;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Vector;
+
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.SourceCode;
+import dol.util.CodePrintStream;
+import dol.util.Copier;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate the main
+ * makefile for the application.
+ *
+ * @author lschor, 2008-10-30
+ *
+ * Revision:
+ * 2008-10-30: Updated the file for the CBE
+ * 2008-11-08: Add double buffering
+ */
+public class CbeProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir target directory
+ */
+ public CbeProcessVisitor(String dir, HashMap<Port, Integer> portMap) {
+ _dir = dir;
+ _portMap = portMap;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be processed
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ Vector<String> pList = new Vector<String>();
+
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ pList.add(basename);
+ p.accept(this);
+ }
+ }
+ } catch (Exception e) {
+ System.out.println("CbeProcessVisitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Visit process.
+ *
+ * @param p process that needs to be processed
+ */
+ public void visitComponent(Process p)
+ {
+ // Differ if the process is a source/sink or a normal process
+ // - Source/Sink: Mapped to the PPE
+ // - Normal process: Mapped to the SPE
+
+ if (p.getNumOfInports() > 0 && p.getNumOfOutports() > 0)
+ {
+ createSPEWrapper(p);
+ }
+ else
+ {
+ createPPEWrapper(p);
+ }
+ }
+
+ /**
+ * Creates a Wrapper for an SPE process
+ *
+ * @param p process that needs to be processed
+ */
+ protected void createSPEWrapper(Process p)
+ {
+ try {
+
+ // Create of each process an own folder
+ // add to this folder the source, the wrapper and a makefile
+ String processDir = _dir + _delimiter + "spu_"
+ + p.getBasename();
+ File dir = new File(processDir);
+ dir.mkdirs();
+
+ // Create the filename for the new wrapper
+ String filename = processDir + _delimiter + "spu_"
+ + p.getBasename() + "_wrapper.c";
+ File process_file = new File(filename);
+ File pattern_file = new File(_dir + _delimiter + _tempDirName
+ + _delimiter + "spu_process_wrapper_template.c");
+ new Copier().copyFile(pattern_file, process_file);
+
+ String includes = "";
+ for (SourceCode code : p.getSrcList()) {
+ includes += "#include \"" + code.getLocality() + "\""
+ + System.getProperty("line.separator");
+ }
+
+ Sed sed = new Sed();
+ // Replace the include of the main c-file
+ sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes);
+ // Replace the process-name in the whole file
+ sed.sed(filename, "@PROCESSNAME@", p.getBasename());
+
+ // Go through all source files
+ for (SourceCode sourceCode : p.getSrcList()) {
+ // Copy the files to the new folder
+ String oldFilename = _dir
+ + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+ filename = processDir
+ + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ if (new File(filename).exists()) {
+ new File(filename).delete();
+ }
+
+ new File(oldFilename).renameTo(new File(filename));
+
+ // Copy also the c-files
+ if ((oldFilename.substring(oldFilename.length() - 2))
+ .equals(".h")) {
+ String newFileNameC = filename.substring(0, filename
+ .length() - 2) + ".c";
+ if (new File(newFileNameC).exists()) {
+ new File(newFileNameC).delete();
+ }
+ new File(oldFilename.substring(
+ 0, oldFilename.length() - 2)
+ + ".c").renameTo(new File(newFileNameC));
+ }
+
+ // Update the files for the DOL project
+ sed.sed(filename, "<dol.h>", "\"dol.h\"");
+
+ // Create the port list
+ for (Port port : p.getPortList()) {
+ Integer portId = _portMap.get(port);
+ if (!port.getBasename().equals(port.getName())) {
+ for (Port port2 : p.getPortList()) {
+ if (port2.getBasename().equals(
+ port.getBasename())) {
+ if (_portMap.get(port2) <
+ _portMap.get(port)) {
+ portId = _portMap.get(port2);
+ }
+ }
+ }
+ }
+
+ // Update the port list with the base names
+ sed.sed(filename, "(#define[ ]+PORT_\\w*[ ]+)\"?"
+ + port.getBasename() + "\"?", "$1 " + portId);
+ }
+
+ // Create the makefile for the process
+ createMakefile(p);
+ }
+ } catch (Exception e) {
+ System.out.println("CbeProcessVisitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates a Wrapper for an SPE process
+ *
+ * @param p process that needs to be processed
+ */
+ protected void createPPEWrapper(Process p)
+ {
+ try {
+ // Create of each process an own folder
+ // add to this folder the source, the wrapper and a makefile
+ String processDir = _dir + _delimiter + "ppu_"
+ + p.getBasename();
+ File dir = new File(processDir);
+ dir.mkdirs();
+
+ // Create the filename for the new wrapper
+ String filename = processDir + _delimiter + "ppu_"
+ + p.getBasename() + "_wrapper.c";
+ File process_file = new File(filename);
+ File pattern_file = new File(_dir + _delimiter + _tempDirName
+ + _delimiter + "ppu_process_wrapper_template.c");
+ new Copier().copyFile(pattern_file, process_file);
+
+ String includes = "";
+ for (SourceCode code : p.getSrcList()) {
+ includes += "#include \"" + code.getLocality() + "\""
+ + System.getProperty("line.separator");
+ }
+
+ Sed sed = new Sed();
+ // Replace the include of the main c-file
+ sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes);
+ // Replace the process-name in the whole file
+ sed.sed(filename, "@PROCESSNAME@", p.getBasename());
+
+ // Go through all source files
+ for (SourceCode sourceCode : p.getSrcList()) {
+ // Copy the files to the new folder
+ String oldFilename = _dir
+ + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+ filename = processDir
+ + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ if (new File(filename).exists()) {
+ new File(filename).delete();
+ }
+
+ new File(oldFilename).renameTo(new File(filename));
+
+ // Copy also the c-files
+ if ((oldFilename.substring(oldFilename.length() - 2))
+ .equals(".h")) {
+ String newFileNameC = filename.substring(0, filename
+ .length() - 2)
+ + ".c";
+ if (new File(newFileNameC).exists()) {
+ new File(newFileNameC).delete();
+ }
+ new File(oldFilename.substring(
+ 0, oldFilename.length() - 2)
+ + ".c").renameTo(new File(newFileNameC));
+ }
+
+ // Update the files for the DOL project
+ sed.sed(filename, "<dol.h>", "\"dol.h\"");
+
+ // Create the port list
+ for (Port port : p.getPortList()) {
+ Integer portId = _portMap.get(port);
+ if (!port.getBasename().equals(port.getName())) {
+ for (Port port2 : p.getPortList()) {
+ if (port2.getBasename().equals(
+ port.getBasename())) {
+ if (_portMap.get(port2) <
+ _portMap.get(port)) {
+ portId = _portMap.get(port2);
+ }
+ }
+ }
+ }
+
+ // Update the port list with the base names
+ sed.sed(filename, "(#define[ ]+PORT_\\w*[ ]+)\"?"
+ + port.getBasename() + "\"?", "$1 " + portId);
+ }
+
+ }
+ } catch (Exception e) {
+ System.out.println("CbeProcessVisitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Create the makefile for a special process -> Each subprocess
+ * gets its own makefile
+ *
+ * @param p process for which the makefile should be created
+ */
+ protected void createMakefile(Process p) {
+ try {
+ // Directory of the process
+ String processDir = _dir + _delimiter + "spu_"
+ + p.getBasename();
+
+ // Create the filename for the new wrapper
+ String filename = processDir + _delimiter + "Makefile";
+ // File makefile = new File(filename);
+
+ OutputStream file;
+
+ file = new FileOutputStream(filename);
+
+ PrintStream _makefilePS = new CodePrintStream(file);
+
+ _makefilePS.println("# Makefile for process " + p.getName());
+ _makefilePS.println("");
+
+ String dependency = "all: spu_" + p.getBasename()
+ + "_wrapper.c ../lib/ProcessWrapper.h "
+ + "../lib/ProcessFifo.h";
+
+ for (SourceCode code: p.getSrcList())
+ {
+ dependency += " " + code.getLocality();
+ }
+
+ _makefilePS.println(dependency);
+ _makefilePS.println("\t spu-g++ -I .. -I ../lib -g -o spu_"
+ + p.getBasename() + "_wrapper spu_" + p.getBasename()
+ + "_wrapper.c -ftree-vectorize -lm -mtune=cell -O3 "
+ + "-fmodulo-sched -funroll-loops -ffast-math");
+ _makefilePS.println("clean: ");
+ _makefilePS.println("\t rm spu_" + p.getBasename()
+ + "_wrapper");
+ _makefilePS.println();
+
+ } catch (FileNotFoundException e) {
+ System.out.println("CbeProcessVisitor - Makefile: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ protected HashMap<Port, Integer> _portMap;
+
+ protected static String _libDirName = "lib";
+ protected static String _tempDirName = "template";
+}
--- /dev/null
+/* $Id: CbeVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.cbe;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Vector;
+
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.Copier;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a CBE package.
+ */
+public class CbeVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param packageName name of the Cbe directory
+ */
+ public CbeVisitor(String packageName) {
+ _packageName = packageName;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param pn process network that needs to be rendered.
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ // Create the library
+ File lib = new File(_packageName + _delimiter + "lib");
+ lib.mkdirs();
+
+ //copy library files
+ File source = new File(_ui.getMySystemCLib().
+ replaceAll("systemC", "cbe").replace("%20", " "));
+ new Copier().copy(source, lib);
+
+ // Create the template
+ File template = new File(_packageName + _delimiter
+ + "template");
+ template.mkdirs();
+
+ //copy the templates
+ source = new File(_ui.getMySystemCLib().
+ replaceAll("systemC", "cbe").
+ replace("lib", "template").replace("%20", " "));
+ new Copier().copy(source, template);
+
+ // Some library files must be copied to the main directory
+ (new File(lib.getPath() + _delimiter + "ppu_main.h")).
+ renameTo(new File (dir.getPath() + _delimiter
+ + "ppu_main.h"));
+
+ //copy process source code
+ source = new File(_srcDirName.replace("%20", " "));
+ new Copier().copy(source, dir);
+
+ createPortMap(pn);
+ pn.accept(new CbeMakefileVisitor(_packageName));
+ pn.accept(new CbeBuildFileVisitor(_packageName));
+ pn.accept(new CbeProcessVisitor(_packageName, _portMap));
+ pn.accept(new CbeModuleVisitor(_packageName, _portMap));
+ pn.accept(new CbeConstantVisitor(_packageName, _portMap));
+ }
+ catch (Exception e) {
+ System.out.println("CbeVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Create a hashmap which maps each port of the given process network
+ * to an integer. For each process, ports are numbered with integers
+ * starting from 0.
+ *
+ * @param pn process network for which the map should be generated
+ */
+ protected void createPortMap(ProcessNetwork pn) {
+ _portMap = new HashMap<Port, Integer>();
+
+ for (Process process : pn.getProcessList()) {
+ int portCount = 0;
+ Vector<Port> portList = process.getPortList();
+ Vector<String> portNameList = new Vector<String>();
+ portNameList.clear();
+ HashMap<String, Integer> portMap =
+ new HashMap<String, Integer>();
+ portMap.clear();
+
+ for (int i = 0; i < portList.size(); i++) {
+ //treat single ports differently than iterated ports
+ String portName = portList.elementAt(i).getName();
+ String baseName = portList.elementAt(i).getBasename();
+
+ if (portName.equals(baseName)) {
+ portNameList.add(portName);
+ portMap.put(portName, portCount++);
+ } else {
+ String range_indices =
+ portList.elementAt(i).getRange();
+ Vector<Integer> range_indices_values =
+ getIndex(range_indices, ";");
+
+ String port_indices = portName;
+ port_indices.replaceAll(baseName, "");
+ Vector<Integer> port_indices_values =
+ getIndex(port_indices, "_");
+
+ if (!portNameList.contains(baseName)) {
+ portNameList.add(baseName);
+ portMap.put(baseName, portCount);
+
+ int size = 1;
+ for (int j = 0;
+ j < range_indices_values.size(); j++) {
+ size *= range_indices_values.elementAt(j);
+ }
+ portCount += size;
+ }
+
+ int portId = portMap.get(baseName);
+ for (int j = 0; j < port_indices_values.size(); j++) {
+ int weight = 1;
+ for (int k = j + 1;
+ k < range_indices_values.size(); k++) {
+ weight *= range_indices_values.elementAt(k);
+ }
+ portId += port_indices_values.elementAt(j)
+ * weight;
+ }
+ portMap.put(portName, portId);
+ }
+ }
+
+ for (int i = 0; i < portList.size(); i++) {
+ _portMap.put(portList.elementAt(i),
+ portMap.get(portList.elementAt(i).getName()));
+ }
+ }
+ }
+
+ /**
+ * Gets vector of indices of a string, where the index must be
+ * separated by the specified separator.
+ * examples:
+ * getIndex("name_1_2", "_", 0) will return 1.
+ * getIndex("name_1_2", "_", 1) will return 2.
+ *
+ * @param range string to parse
+ * @param separator delimiter of indices
+ * @return vector of indices
+ */
+ protected Vector<Integer> getIndex(String range, String separator) {
+ Vector<Integer> indices = new Vector<Integer>();
+ String[] subranges = range.split(separator);
+ for (int i = 0; i < subranges.length; i++) {
+ try {
+ int value = Integer.valueOf(subranges[i]);
+ indices.add(value);
+ } catch (Exception e) {
+ continue;
+ }
+ }
+ return indices;
+ }
+
+ protected HashMap<Port, Integer> _portMap;
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+}
--- /dev/null
+/**************************************************************** \r
+ * FIFO Functions\r
+ * Creator: lschor, 2008-10-30\r
+ * Description: Defines Main functions for a FIFO in the Local Store of a SPE\r
+ * \r
+ * Revision: \r
+ * - 2008-11-08: Created\r
+ * - 2008-11-15: Added Performance Estimation methods\r
+ */\r
+\r
+#ifndef _PROCESS_FIFO_H_\r
+#define _PROCESS_FIFO_H_\r
+\r
+// Maximum data allowed in the FIFO\r
+static const int MAXELEMENT = 1024; \r
+\r
+// Varialbes to store a fifo-read process\r
+uint32_t tag_id_read = 99;\r
+uint32_t lenRead = 0; \r
+uint32_t queueRead = 0; \r
+char * resultRead; \r
+\r
+char *locBuf[NUM_FIFO];\r
+int locBufCount[NUM_FIFO]; \r
+int locBufStart[NUM_FIFO]; \r
+\r
+// How many is free in a fifo\r
+uint32_t freespaceQueue(int queue)\r
+{\r
+ return MAXELEMENT - locBufCount[queue]; \r
+}\r
+\r
+\r
+// Init all fifos\r
+void initQueues()\r
+{\r
+ int j; \r
+ for (j = 0; j < NUM_FIFO; j++)\r
+ {\r
+ locBuf[j] = NULL;\r
+ locBufCount[j] = 0;\r
+ locBufStart[j] = 0;\r
+ }\r
+}\r
+\r
+// Init a special queue\r
+void initLocBuf(int queue)\r
+{\r
+ locBuf[queue] = NULL;\r
+ locBufCount[queue] = 0;\r
+ locBufStart[queue] = 0;\r
+}\r
+\r
+// Gives the memory of the buffers free\r
+void deinitLocBuf()\r
+{\r
+ int j; \r
+ for (j = 0; j < NUM_FIFO; j++)\r
+ {\r
+ if (locBuf[j] != NULL)\r
+ {\r
+ free(locBuf[j]);\r
+ }\r
+ }\r
+}\r
+\r
+void updateLocBuf(int queue)\r
+{\r
+ // If the buffer is used the first time, allocate him\r
+ if (locBuf[queue]== NULL)\r
+ {\r
+ locBuf[queue] = (char *)malloc(MAXELEMENT * sizeof(char));\r
+ }\r
+#ifdef MEASURE_DOL_READ_START_DMA\r
+ double t_dol_read_start_dma = spu_read_decrementer();\r
+#endif\r
+\r
+ // Double-Buffering --> Try to close the old read-process\r
+ if (tag_id_read != 99)\r
+ {\r
+ waittag(tag_id_read); \r
+ // Write the data you read into the queue; \r
+ int i; \r
+\r
+ #ifdef MEASURE_DOL_READ_DOUBLEBUF\r
+ double t_dol_read_doublebuf = spu_read_decrementer();\r
+ #endif\r
+\r
+ // Has to write all elements at the beginning or write all elements at the end of the buffer\r
+ if (locBufStart[queueRead] + locBufCount[queueRead] > MAXELEMENT || locBufStart[queueRead] + locBufCount[queueRead] + lenRead < MAXELEMENT)\r
+ {\r
+ memcpy(&(locBuf[queueRead][(locBufStart[queueRead] + locBufCount[queueRead]) % MAXELEMENT]), resultRead, lenRead);\r
+ }\r
+ \r
+ // Otherwise something at the end and something at the beginning\r
+ else\r
+ {\r
+ // At the end of the buffer\r
+ memcpy(&(locBuf[queueRead][(locBufStart[queueRead] + locBufCount[queueRead])]), resultRead, MAXELEMENT - locBufStart[queueRead] - locBufCount[queueRead]);\r
+ \r
+ // At the beginning\r
+ memcpy(locBuf[queueRead], &(resultRead[MAXELEMENT - locBufStart[queueRead] - locBufCount[queueRead]]), lenRead - (MAXELEMENT - locBufStart[queueRead] - locBufCount[queueRead]));\r
+ }\r
+\r
+ locBufCount[queueRead]+=lenRead;\r
+\r
+ #ifdef MEASURE_DOL_READ_DOUBLEBUF\r
+ t_dol_read_doublebuf -= spu_read_decrementer();\r
+ printf("DOL_READ_DOUBLEBUF_DMA;%f\n",t_dol_read_doublebuf * 1 / MEASURE_CPU);\r
+ #endif\r
+\r
+ mfc_tag_release(tag_id_read); // release tag ID before exiting\r
+ _free_align(resultRead);\r
+\r
+ // Send a okey about the data to the PPE\r
+ spu_write_out_mbox((uint32_t)(SPE_READ_SUC << 28)); // stalls mailbox is full.\r
+ tag_id_read = 99; \r
+ }\r
+ \r
+ uint32_t message = (SPE_READ_DEMAND << 28) | (queue << 16) | (freespaceQueue(queue));\r
+\r
+#ifdef MEASURE_DOL_READ_HANDSHAKE\r
+ double t_dol_read_handshake = spu_read_decrementer();\r
+#endif\r
+\r
+ spu_write_out_mbox((uint32_t)(message)); \r
+ \r
+ message = spu_read_in_mbox(); \r
+ uint32_t request = message >> 28; \r
+ lenRead = (0xffff & message);\r
+\r
+ if (request != (uint32_t) 1)\r
+ {\r
+ return; \r
+ }\r
+ \r
+ if((tag_id_read=mfc_tag_reserve())==MFC_TAG_INVALID){\r
+ printf("SPE: ERROR - can't reserve a tag ID\n"); return;\r
+ }\r
+ \r
+ // Wait for the response of the PPE --> The address where to read\r
+ uint32_t ea_mfc_h, ea_mfc_l;\r
+ uint64_t ea_mfc;\r
+ \r
+ ea_mfc_h = spu_read_in_mbox(); \r
+ ea_mfc_l = spu_read_in_mbox();\r
+ ea_mfc = mfc_hl2ea(ea_mfc_h, ea_mfc_l); \r
+\r
+#ifdef MEASURE_DOL_READ_HANDSHAKE\r
+ t_dol_read_handshake -= spu_read_decrementer();\r
+ printf("DOL_READ_HANDSHAKE;%f\n",t_dol_read_handshake * 1 / MEASURE_CPU);\r
+#endif\r
+\r
+#ifdef MEASURE_DOL_READ_START_DMA\r
+ t_dol_read_start_dma -= spu_read_decrementer();\r
+ printf("DOL_READ_START_DMA;%f\n",t_dol_read_start_dma * 1 / MEASURE_CPU);\r
+#endif\r
+\r
+ resultRead = (char *)_malloc_align(lenRead, 4); \r
+\r
+#ifdef MEASURE_DOL_READ_DMA\r
+ double t_dol_read_dma = spu_read_decrementer();\r
+#endif\r
+ \r
+ // Read the data from the address we got from the PPE\r
+ mfc_get(&(resultRead[0]), ea_mfc, lenRead, tag_id_read, 0, 0); \r
+#ifdef MEASURE_DOL_READ_DMA\r
+ t_dol_read_dma -= spu_read_decrementer();\r
+ printf("DOL_READ_DMA;%f\n",t_dol_read_dma * 1 / MEASURE_CPU);\r
+#endif\r
+\r
+ queueRead = queue; \r
+}\r
+\r
+// Read from the local buffer\r
+void readLocBuf(int queue, void *destination, int len)\r
+{\r
+#ifdef MEASURE_DOL_READ_LOCBUF\r
+ double t_dol_read_locbuf = spu_read_decrementer();\r
+#endif\r
+ int count = 0;\r
+ int newLen = 0;\r
+ char* buffer = (char*) destination;\r
+ int i; \r
+\r
+ while (count < len)\r
+ {\r
+ newLen = (len - count) > MAXELEMENT? MAXELEMENT : len - count;\r
+ \r
+ while (locBufCount[queue] < newLen)\r
+ {\r
+ updateLocBuf(queue); \r
+ }\r
+\r
+ // Can directly read all elements from the end of the buffer\r
+ if (locBufStart[queue] + newLen < MAXELEMENT)\r
+ {\r
+ memcpy(buffer, &(locBuf[queue][locBufStart[queue]]), newLen);\r
+ }\r
+\r
+ // Has to write from the end and from the beginning of the buffer\r
+ else\r
+ {\r
+ memcpy(&(buffer[count]), &(locBuf[queue][locBufStart[queue]]), MAXELEMENT - locBufStart[queue]);\r
+ memcpy(&(buffer[count + MAXELEMENT - locBufStart[queue]]), locBuf[queue], newLen - MAXELEMENT + locBufStart[queue]);\r
+ }\r
+\r
+ locBufCount[queue] -= newLen;\r
+ locBufStart[queue] = (locBufStart[queue] + newLen) % MAXELEMENT; \r
+ count += newLen;\r
+ }\r
+#ifdef MEASURE_DOL_READ_LOCBUF\r
+ t_dol_read_locbuf -= spu_read_decrementer();\r
+ printf("DOL_READ_LOCBUF;%f\n",t_dol_read_locbuf * 1 / MEASURE_CPU);\r
+#endif\r
+}\r
+\r
+\r
+#endif // _PROCESS_FIFO_H_ \r
--- /dev/null
+/**************************************************************** \r
+ * Process Wrapper Functions\r
+ * Creator: lschor, 2008-10-30\r
+ * Description: General process wrapper file, includes DOL_read and DOL_write as main functions\r
+ * \r
+ * Revision: \r
+ * - 2008-10-30: Created\r
+ * - 2008-11-08: Update to Double Buffering\r
+ * - 2008-11-15: Added Performance Estimation methods\r
+ */\r
+\r
+#ifndef __PROCESS_WRAPPER_H__\r
+#define __PROCESS_WRAPPER_H__\r
+\r
+#include <spu_intrinsics.h>\r
+#include <spu_mfcio.h>\r
+#include <string.h>\r
+#include <stdio.h>\r
+#include <stdarg.h> // Used for va_list\r
+#include <stdlib.h>\r
+#include "lib/malloc_align.h" // Malloc for DMA\r
+#include "lib/free_align.h" // Free for DMA\r
+#include "dol.h"\r
+#include "common.h"\r
+#include "estimation.h"\r
+\r
+//Cell Macros\r
+#define waittag(tag_id) mfc_write_tag_mask(1<<tag_id); mfc_read_tag_status_all();\r
+\r
+//DOL macros\r
+#define GETINDEX(dimension) \\r
+ ((ProcessWrapper*)(p->wptr))->index[dimension]\r
+\r
+#define CREATEPORTVAR(name) \\r
+ int name\r
+\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+ createPort(&port, base, number_of_indices, index_range_pairs)\r
+\r
+// Include the FIFO Functions\r
+#include "lib/ProcessFifo.h"\r
+\r
+// Include some help functions\r
+#include "lib/ProcessWrapperHelp.h"\r
+\r
+// Struct for a process\r
+typedef struct _process_wrapper {\r
+ char* name;\r
+ uint32_t* index;\r
+ uint32_t is_detached;\r
+ uint32_t* port_id;\r
+ uint32_t* port_queue_id;\r
+ uint32_t number_of_ports;\r
+} ProcessWrapper;\r
+\r
+// Tag address for the write process\r
+uint32_t tag_id_write = 99; \r
+\r
+// Pointer to the current data buffer\r
+char * resultWrite; \r
+\r
+/**\r
+ * Finish a DOL_write process\r
+ */\r
+void finish_DOL_write()\r
+{\r
+ if (tag_id_write != 99)\r
+ {\r
+ #ifdef MEASURE_DOL_WRITE_FINISH\r
+ double t_dol_write_finish = spu_read_decrementer();\r
+ #endif\r
+\r
+ // Wait until the write process is finished\r
+ waittag(tag_id_write);\r
+ mfc_tag_release(tag_id_write); // release tag ID before exiting\r
+ _free_align(resultWrite);\r
+ // Send a okey about the data to the PPE\r
+ spu_write_out_mbox((uint32_t)(SPE_WRITE_SUC << 28)); // stalls mailbox is full.\r
+ tag_id_write = 99; \r
+ //queueWrite = -1;\r
+\r
+ #ifdef MEASURE_DOL_WRITE_FINISH\r
+ t_dol_write_finish -= spu_read_decrementer();\r
+ printf("DOL_WRITE_FINISH;%f\n",t_dol_write_finish * 1 / MEASURE_CPU);\r
+ #endif\r
+\r
+ }\r
+}\r
+\r
+/**\r
+ * Read from the FIFO\r
+ */\r
+void DOL_read(void *port, void *buf, int len, DOLProcess *process)\r
+{\r
+#ifdef MEASURE_DOL_READ\r
+ double t_dol_read = spu_read_decrementer();\r
+#endif\r
+\r
+ ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
+ int i; \r
+\r
+ for (i = 0; i < process_wrapper->number_of_ports; i++) \r
+ {\r
+ if (process_wrapper->port_id[i] == (int)port) \r
+ {\r
+ int queue = process_wrapper->port_queue_id[i];\r
+\r
+ finish_DOL_write(); \r
+ \r
+ // Try to get new data into the local Buffer\r
+ updateLocBuf(queue); \r
+ \r
+ // Read from the Buffer\r
+ readLocBuf(queue, buf, len); \r
+ \r
+ break; \r
+ }\r
+ }\r
+#ifdef MEASURE_DOL_READ\r
+ t_dol_read -= spu_read_decrementer();\r
+ printf("DOL_READ;%f\n",t_dol_read * 1 / MEASURE_CPU);\r
+#endif\r
+\r
+}\r
+\r
+\r
+/**\r
+ * Write data into the FIFO\r
+ */\r
+void DOL_write(void *port, void *buf, int len, DOLProcess *process)\r
+{\r
+#ifdef MEASURE_DOL_WRITE\r
+ double t_dol_write = spu_read_decrementer();\r
+#endif\r
+\r
+ ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
+ int i; \r
+ \r
+ for (i = 0; i < process_wrapper->number_of_ports; i++) \r
+ {\r
+ if (process_wrapper->port_id[i] == (int)port) \r
+ {\r
+ // This is our queue\r
+ int queue = process_wrapper->port_queue_id[i];\r
+ \r
+ #ifdef MEASURE_DOL_WRITE_START_DMA\r
+ double t_dol_write_start_dma = spu_read_decrementer();\r
+ #endif\r
+\r
+ // There has been a writing process. Is it already finished? \r
+ finish_DOL_write(); \r
+\r
+ // Create the new write process\r
+ \r
+ // reserve DMA tag ID\r
+ if((tag_id_write=mfc_tag_reserve())==MFC_TAG_INVALID){\r
+ printf("SPE: ERROR - can't reserve a tag ID\n"); return;\r
+ }\r
+\r
+ // Create the message we like to send, format: \r
+ // 4 bit: code (total 16 possibilities)\r
+ // 12 bit: queue (total 4096 possibilities)\r
+ // 16 bit: len (total maximal size of 512 KB which could be send)\r
+ uint32_t message = (SPE_WRITE_DEMAND << 28) | (queue << 16) | (len); \r
+\r
+ #ifdef MEASURE_DOL_WRITE_HANDSHAKE\r
+ double t_dol_write_handshake = spu_read_decrementer();\r
+ #endif\r
+ // Demand the PPE for an address\r
+ spu_write_out_mbox(message); \r
+\r
+ // Copy the data into the right data-alignment\r
+ resultWrite = (char *)_malloc_align(roundDMA(len), 4); \r
+ memcpy(resultWrite, buf, len); \r
+ \r
+ // Is there enough free space to write into the queues? \r
+ uint32_t messageIn = spu_read_in_mbox(); \r
+ uint32_t request = messageIn >> 28; \r
+ \r
+ while (request != (uint32_t) 1)\r
+ {\r
+ spu_write_out_mbox(message); \r
+ messageIn = spu_read_in_mbox(); \r
+ request = messageIn >> 28; \r
+ }\r
+\r
+ // Wait for the response of the PPE, i.e. the address for the FIFO element\r
+ uint32_t ea_mfc_h, ea_mfc_l;\r
+ uint64_t ea_mfc;\r
+ ea_mfc_h = spu_read_in_mbox();\r
+ ea_mfc_l = spu_read_in_mbox();\r
+ ea_mfc = mfc_hl2ea(ea_mfc_h, ea_mfc_l);\r
+\r
+ #ifdef MEASURE_DOL_WRITE_HANDSHAKE\r
+ t_dol_write_handshake -= spu_read_decrementer();\r
+ printf("DOL_WRITE_HANDSHAKE;%f\n",t_dol_write_handshake * 1 / MEASURE_CPU);\r
+ #endif\r
+\r
+\r
+ #ifdef MEASURE_DOL_WRITE_START_DMA\r
+ t_dol_write_start_dma -= spu_read_decrementer();\r
+ printf("DOL_WRITE_START_DMA;%f\n",t_dol_write_start_dma * 1 / MEASURE_CPU);\r
+ #endif\r
+\r
+ #ifdef MEASURE_DOL_WRITE_DMA\r
+ double t_dol_write_dma = spu_read_decrementer();\r
+ #endif\r
+ \r
+ // Write the data to the address we got from the PPE\r
+ mfc_put((void *)&(resultWrite[0]), ea_mfc, roundDMA(len), tag_id_write, 0, 0); \r
+\r
+ #ifdef MEASURE_DOL_WRITE_DMA\r
+ t_dol_write_dma -= spu_read_decrementer();\r
+ printf("DOL_WRITE_DMA;%f\n",t_dol_write_dma * 1 / MEASURE_CPU);\r
+ #endif\r
+\r
+\r
+ break;\r
+ }\r
+ }\r
+#ifdef MEASURE_DOL_WRITE\r
+ t_dol_write -= spu_read_decrementer();\r
+ printf("DOL_WRITE;%f\n",t_dol_write * 1 / MEASURE_CPU);\r
+#endif\r
+}\r
+\r
+/**\r
+ * Detach the DOL Process\r
+ */\r
+void DOL_detach(DOLProcess *process) {\r
+ //printf("[%s] DOL_detach.\n", (char*)(((ProcessWrapper*)process->wptr)->name));\r
+\r
+ // Check if all write processes are finished\r
+ if (tag_id_write != 99)\r
+ {\r
+ waittag(tag_id_write);\r
+ mfc_tag_release(tag_id_write); // release tag ID before exiting\r
+ _free_align(resultWrite); \r
+ spu_write_out_mbox((uint32_t)(2 << 28)); // stalls mailbox is full.\r
+ }\r
+\r
+ uint32_t message = (SPE_DETACH << 28); \r
+ spu_write_out_mbox(message); \r
+ deinitLocBuf();\r
+ ((ProcessWrapper*)process->wptr)->is_detached = 1;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/**************************************************************** \r
+ * Process Wrapper Help functions\r
+ * Creator: lschor, 2008-11-21\r
+ * Description: General process wrapper fucntions\r
+ * \r
+ * Revision: \r
+ * - 2008-11-21: Created\r
+ */\r
+\r
+#ifndef __PROCESS_WRAPPER_HELP_H__\r
+#define __PROCESS_WRAPPER_HELP_H__\r
+\r
+#include <stdarg.h> // Used for va_list\r
+\r
+/**\r
+ * Gets an index of a string, where the index must be separated by\r
+ * a character specified in tokens.\r
+ * Returns -1, when an error occurs.\r
+ *\r
+ * Example:\r
+ * getIndex("name_1_2", "_", 0) will return 1.\r
+ * getIndex("name_1_2", "_", 1) will return 2.\r
+ *\r
+ * @param string string to parse\r
+ * @param tokens delimiter of indices\r
+ * @param indexNumber position of index (starting at 0)\r
+ */\r
+int getIndex(const char* string, char* tokens, int indexNumber) {\r
+ char* string_copy;\r
+ char* token_pointer;\r
+ int index = 0;\r
+\r
+ string_copy = (char*) malloc(sizeof(char) * (strlen(string) + 1));\r
+ if (!string_copy) {\r
+ fprintf(stderr, "getIndex(): could not allocate memory.\n");\r
+ return -1;\r
+ }\r
+\r
+ strcpy(string_copy, string);\r
+\r
+ token_pointer = strtok(string_copy, tokens);\r
+ do {\r
+ token_pointer = strtok(NULL, tokens);\r
+ index++;\r
+ } while (index <= indexNumber && token_pointer != 0);\r
+\r
+ if (token_pointer) {\r
+ index = atoi(token_pointer);\r
+ free(string_copy);\r
+ return index;\r
+ }\r
+\r
+ free(string_copy);\r
+ return -1;\r
+}\r
+\r
+/**\r
+ * Create the port name of an iterated port based on its basename and the\r
+ * given indices.\r
+ *\r
+ * @param port buffer where the result is stored (created using\r
+ * CREATEPORTVAR)\r
+ * @param base basename of the port\r
+ * @param number_of_indices number of dimensions of the port\r
+ * @param index_range_pairs index and range values for each dimension\r
+ */\r
+int *createPort(int *port, int base, int number_of_indices,\r
+ int index_range_pairs, ...) {\r
+ int index[4];\r
+ int range[4];\r
+ int i;\r
+ int value;\r
+\r
+ va_list marker;\r
+ va_start(marker, index_range_pairs);\r
+\r
+ value = index_range_pairs;\r
+ for (i = 0; i < number_of_indices; i++) {\r
+ index[i] = value;\r
+ value = va_arg(marker, int);\r
+ range[i] = value;\r
+ if (i < number_of_indices - 1) {\r
+ value = va_arg(marker, int);\r
+ }\r
+ }\r
+\r
+ *port = base;\r
+ for (i = 0; i < number_of_indices; i++) {\r
+ int j;\r
+ int weight = 1;\r
+ for (j = 1; j < number_of_indices - i; j ++) {\r
+ weight *= range[j];\r
+ }\r
+ *port += index[i] * weight;\r
+ }\r
+\r
+ return port;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/**************************************************************** \r
+ * Process Wrapper Functions\r
+ * Creator: lschor, 2008-10-30\r
+ * Description: General process wrapper file, includes DOL_read and DOL_write as main functions\r
+ * \r
+ * Revision: \r
+ * - 2008-10-30: Created\r
+ * - 2008-11-08: Update to Double Buffering\r
+ * - 2008-11-15: Added Performance Estimation methods\r
+ */\r
+\r
+#ifndef __PROCESS_WRAPPER_PPE_H__\r
+#define __PROCESS_WRAPPER_PPE_H__\r
+\r
+#include <pthread.h>\r
+#include <stdio.h>\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <stdlib.h>\r
+#include <time.h>\r
+\r
+#include "common_ppu.h"\r
+#include "dol.h"\r
+#include "ProcessWrapperHelp.h"\r
+\r
+\r
+/**\r
+ * Read from the FIFO\r
+ */\r
+void DOL_read(void *port, void *buf, int len, DOLProcess *process)\r
+{\r
+ ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
+ int i; \r
+\r
+ for (i = 0; i < process_wrapper->number_of_ports; i++) \r
+ {\r
+ if (process_wrapper->port_id[i] == (uint64_t)port) \r
+ {\r
+ int queue = process_wrapper->port_queue_id[i];\r
+ int i = 0; \r
+ struct timespec t;\r
+ t.tv_sec = 0;\r
+ t.tv_nsec = 5;\r
+ \r
+\r
+ while (process_wrapper->locBufCount[queue] < len)\r
+ {\r
+ nanosleep(&t, NULL);\r
+ };\r
+\r
+ char *buffer = (char *)buf;\r
+\r
+ pthread_mutex_lock( &(process_wrapper->mutex[queue]) );\r
+\r
+ // Can directly read all elements from the end of the buffer\r
+ if (process_wrapper->locBufStart[queue] + len < process_wrapper->MAXELEMENT)\r
+ {\r
+ memcpy(buffer, &(process_wrapper->locBuf[queue][process_wrapper->locBufStart[queue]]), len);\r
+ }\r
+\r
+ // Has to write from the end and from the beginning of the buffer\r
+ else\r
+ {\r
+ memcpy(&(buffer[0]), &(process_wrapper->locBuf[queue][process_wrapper->locBufStart[queue]]), process_wrapper->MAXELEMENT - process_wrapper->locBufStart[queue]);\r
+ memcpy(&(buffer[process_wrapper->MAXELEMENT - process_wrapper->locBufStart[queue]]), process_wrapper->locBuf[queue], len - process_wrapper->MAXELEMENT + process_wrapper->locBufStart[queue]);\r
+ }\r
+\r
+ process_wrapper->locBufCount[queue] -= len;\r
+ process_wrapper->locBufStart[queue] = (process_wrapper->locBufStart[queue] + len) % process_wrapper->MAXELEMENT;\r
+\r
+ pthread_mutex_unlock( & (process_wrapper->mutex[queue]) );\r
+\r
+\r
+ break; \r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ * Write data into the FIFO\r
+ */\r
+void DOL_write(void *port, void *buf, int len, DOLProcess *process)\r
+{\r
+ ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
+ int i; \r
+ \r
+ for (i = 0; i < process_wrapper->number_of_ports; i++) \r
+ {\r
+ if (process_wrapper->port_id[i] == (uint64_t)port) \r
+ {\r
+ // This is our queue\r
+ int queue = process_wrapper->port_queue_id[i];\r
+\r
+ struct timespec t;\r
+ t.tv_sec = 0;\r
+ t.tv_nsec = 5;\r
+\r
+ // Wait if there is not enough space in the fifo \r
+ while (process_wrapper->MAXELEMENT - process_wrapper->locBufCount[queue] < len)\r
+ {\r
+ nanosleep(&t, NULL);\r
+ };\r
+\r
+ char *buffer = (char *)buf;\r
+\r
+ pthread_mutex_lock( &(process_wrapper->mutex[queue]) );\r
+\r
+ // Has to write all elements at the beginning or write all elements at the end of the buffer\r
+ if (process_wrapper->locBufStart[queue] + process_wrapper->locBufCount[queue] > process_wrapper->MAXELEMENT || process_wrapper->locBufStart[queue] + process_wrapper->locBufCount[queue] + len < process_wrapper->MAXELEMENT)\r
+ {\r
+ memcpy(&(process_wrapper->locBuf[queue][(process_wrapper->locBufStart[queue] + process_wrapper->locBufCount[queue]) % process_wrapper->MAXELEMENT]), buffer, len);\r
+ }\r
+\r
+ // Otherwise something at the end and something at the beginning\r
+ else\r
+ {\r
+ // At the end of the buffer\r
+ memcpy(&(process_wrapper->locBuf[queue][(process_wrapper->locBufStart[queue] + process_wrapper->locBufCount[queue])]), buffer, process_wrapper->MAXELEMENT - process_wrapper->locBufStart[queue] - process_wrapper->locBufCount[queue]);\r
+\r
+ // At the beginning\r
+ memcpy(process_wrapper->locBuf[queue], &(buffer[process_wrapper->MAXELEMENT - process_wrapper->locBufStart[queue] - process_wrapper->locBufCount[queue]]), len - (process_wrapper->MAXELEMENT - process_wrapper->locBufStart[queue] - process_wrapper->locBufCount[queue]));\r
+ }\r
+\r
+ process_wrapper->locBufCount[queue]+=len;\r
+\r
+ pthread_mutex_unlock( & (process_wrapper->mutex[queue]) );\r
+\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ * Detach the DOL Process\r
+ */\r
+void DOL_detach(DOLProcess *process) {\r
+ ProcessWrapper* process_wrapper = (ProcessWrapper*)process->wptr;\r
+ printf("[%s] DOL_detach.\n", (char*)(((ProcessWrapper*)process->wptr)->name));\r
+ \r
+ pthread_mutex_lock( (process_wrapper->mutexProcessNr) );\r
+ (* process_wrapper->processFinished)++;\r
+ pthread_mutex_unlock( (process_wrapper->mutexProcessNr) );\r
+\r
+ ((ProcessWrapper*)process->wptr)->is_detached = 1;\r
+}\r
+\r
+#endif\r
--- /dev/null
+/**************************************************************** \r
+ * COMMON.H\r
+ * Creator: lschor, 2008-10-30\r
+ * Description: Specifies some structs and Constants for the CBE-DOL-Implementation\r
+ * \r
+ * Revision: \r
+ * - 2008-10-30: Created\r
+ */\r
+\r
+#ifndef _COMMON_H_\r
+#define _COMMON_H_\r
+\r
+#include "dol.h"\r
+#include "lib/constant.h"\r
+\r
+#define SPE_WRITE_DEMAND 0\r
+#define SPE_READ_DEMAND 1\r
+#define SPE_WRITE_SUC 2\r
+#define SPE_READ_SUC 3\r
+#define SPE_DETACH 4\r
+\r
+// the context that PPE forward to SPE\r
+typedef struct{\r
+ uint64_t port_id;\r
+ uint64_t port_queue_id; \r
+\r
+ uint64_t processName; // Address for the name of the process\r
+ uint64_t processNameLen; // Len of the process Name\r
+\r
+ uint32_t number_of_ports; \r
+ uint32_t is_detached; \r
+ uint32_t padd[2]; // dummy - for alignment --> It always has to be a multiple of 128 bit! \r
+} parm_context; // aligned to 16B \r
+\r
+typedef struct{\r
+ uint32_t d; \r
+ uint32_t padd[31]; //padd to cache line\r
+} status_s;\r
+\r
+\r
+// Round a number ot the right DMA number --> Is used for DMA transfers\r
+uint32_t roundDMA(uint32_t number)\r
+{\r
+ if (number > 16)\r
+ return number + 16 - (number % 16);\r
+ else if (number > 8)\r
+ return 16; \r
+ else if (number > 4)\r
+ return 8; \r
+ else if (number > 2)\r
+ return 4; \r
+ else if (number > 1)\r
+ return 2; \r
+ else \r
+ return 1; \r
+}\r
+\r
+#endif // _COMMON_H_ \r
+\r
--- /dev/null
+/**************************************************************** \r
+ * Common structs for the PPU\r
+ * Creator: lschor, 2008-11-21\r
+ * Description: Common structs for the PPU\r
+ * \r
+ * Revision: \r
+ * - 2008-11-21: Created\r
+ */\r
+\r
+#ifndef __COMMON_PPU_H__\r
+#define __COMMON_PPU_H__\r
+\r
+//DOL macros\r
+#define GETINDEX(dimension) \\r
+ ((ProcessWrapper*)(p->wptr))->index[dimension]\r
+\r
+#define CREATEPORTVAR(name) \\r
+ int name\r
+\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+ createPort(&port, base, number_of_indices, index_range_pairs)\r
+\r
+\r
+// Struct for a process\r
+typedef struct _process_wrapper {\r
+ char* name;\r
+ uint32_t* index;\r
+ uint32_t is_detached;\r
+ volatile uint32_t* port_id;\r
+ volatile uint32_t* port_queue_id;\r
+ uint32_t number_of_ports;\r
+ char ** locBuf;\r
+ int * locBufCount;\r
+ int * locBufStart;\r
+ int MAXELEMENT;\r
+ int * processFinished;\r
+ pthread_mutex_t * mutex;\r
+ pthread_mutex_t * mutexProcessNr;\r
+} ProcessWrapper;\r
+\r
+#endif\r
--- /dev/null
+#ifndef __DOL_H__
+#define __DOL_H__
+
+//structure for local memory of process
+typedef struct _local_states *LocalState;
+
+//structure for process
+struct _process;
+
+//
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr;
+} DOLProcess;
+
+void DOL_read(void *port, void *buf, int len, DOLProcess *process);
+void DOL_write(void *port, void *buf, int len, DOLProcess *process);
+void DOL_detach(DOLProcess *process);
+int getIndex(const char* string, char* tokens, int indexNumber);
+int *createPort(int *port, int base, int number_of_indices, int index_range_pairs, ...);
+
+#endif
--- /dev/null
+/**************************************************************** \r
+ * Estimation Defintions\r
+ * Creator: lschor, 2008-11-15\r
+ * Description: File with includes for time measurements\r
+ * Principle: if 1 then this point will be measured, if 0 then this point will not be measured\r
+ * \r
+ * Revision: \r
+ * - 2008-11-15: Created\r
+ */\r
+\r
+// \r
+#ifndef __ESTIMATION_H__\r
+#define __ESTIMATION_H__\r
+\r
+// What to measure?\r
+//#define MEASURE 0 // Measure activeted\r
+\r
+#ifdef MEASURE\r
+ //#define MEASURE_DOL_READ 0 // Measure DOL READ\r
+ //#define MEASURE_DOL_READ_FINISH 0 // Measure FINISH DOL Read\r
+ //#define MEASURE_DOL_READ_START_DMA 0 // Measure Time from start until the DMA process has started\r
+ //#define MEASURE_DOL_READ_HANDSHAKE 0 // Measure Time of the whole handshake\r
+ //#define MEASURE_DOL_READ_DMA 0 // Measure Time of DMA Setup\r
+ //#define MEASURE_DOL_READ_LOCBUF 0 // Measure Time for LocBuf read\r
+ //#define MEASURE_DOL_READ_DOUBLEBUF 0 // Measure Time for writing into the buffer\r
+\r
+ //#define MEASURE_DOL_WRITE 0 // Measure DOL WRITE\r
+ //#define MEASURE_DOL_WRITE_FINISH 0 // Measure FINISH DOL Write\r
+ //#define MEASURE_DOL_WRITE_START_DMA 0 // Measure Time from start until the DMA process has started\r
+ //#define MEASURE_DOL_WRITE_HANDSHAKE 0 // Measure Time of the whole handshake\r
+ //#define MEASURE_DOL_WRITE_DMA 0 // Measure Time of DMA Setup\r
+\r
+ //#define MEASURE_DOL_FIRE 0 // Measure DOL FIRE\r
+ //#define MEASURE_DOL_INIT 0 // Measure DOL INIT\r
+ //#define MEASURE_SPE 0 // Measure whole SPE process\r
+\r
+ //#define MEASURE_APPLICATION 0 // Measure whole execution time\r
+ //#define MEASURE_SET_UP_SPE_THREAD 0 // Measure time to set up the SPE-threads\r
+ //#define MEASURE_SPE_WRITE_DEMAND 0 // Measure time of write demand\r
+ //#define MEASURE_SPE_READ_DEMAND 0 // Measure time of read demand\r
+ //#define MEASURE_SPE_WRITE_SUC 0 // Measure time of write successful\r
+ //#define MEASURE_SPE_READ_SUC 0 // Measure time of read successful\r
+\r
+#endif\r
+\r
+// Some constants\r
+#define MEASURE_START 0xFFFFFFFF // Start decrementer at this value\r
+#define MEASURE_CPU 79800000.0 // Timebase PS3 (in Hz)\r
+\r
+#endif\r
--- /dev/null
+/* -------------------------------------------------------------- */
+/* (C)Copyright 2001,2006, */
+/* International Business Machines Corporation, */
+/* Sony Computer Entertainment, Incorporated, */
+/* Toshiba Corporation, */
+/* */
+/* All Rights Reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or */
+/* without modification, are permitted provided that the */
+/* following conditions are met: */
+/* */
+/* - Redistributions of source code must retain the above copyright*/
+/* notice, this list of conditions and the following disclaimer. */
+/* */
+/* - Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials */
+/* provided with the distribution. */
+/* */
+/* - Neither the name of IBM Corporation nor the names of its */
+/* contributors may be used to endorse or promote products */
+/* derived from this software without specific prior written */
+/* permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
+/* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
+/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
+/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR */
+/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT */
+/* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
+/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
+/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */
+/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR */
+/* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
+/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/* -------------------------------------------------------------- */
+/* PROLOG END TAG zYx */
+#ifndef _FREE_ALIGN_H_
+#define _FREE_ALIGN_H_ 1
+
+#include <stdlib.h>
+
+/* Function
+ *
+ * void free_align(void *ptr)
+ *
+ * Description
+ * The free_align routine frees a memory buffer allocate by the
+ * malloc_align routine. See malloc_align for complete details.
+ */
+
+static __inline void _free_align(void *ptr)
+{
+ void * real;
+
+ if (ptr) {
+ real = *((void **)(ptr)-1);
+ free(real);
+ }
+}
+
+#endif /* _FREE_ALIGN_H_ */
--- /dev/null
+/* -------------------------------------------------------------- */
+/* (C)Copyright 2001,2007, */
+/* International Business Machines Corporation, */
+/* Sony Computer Entertainment, Incorporated, */
+/* Toshiba Corporation, */
+/* */
+/* All Rights Reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or */
+/* without modification, are permitted provided that the */
+/* following conditions are met: */
+/* */
+/* - Redistributions of source code must retain the above copyright*/
+/* notice, this list of conditions and the following disclaimer. */
+/* */
+/* - Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials */
+/* provided with the distribution. */
+/* */
+/* - Neither the name of IBM Corporation nor the names of its */
+/* contributors may be used to endorse or promote products */
+/* derived from this software without specific prior written */
+/* permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
+/* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
+/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
+/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR */
+/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT */
+/* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
+/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
+/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */
+/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR */
+/* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
+/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/* -------------------------------------------------------------- */
+/* PROLOG END TAG zYx */
+
+#ifndef _MALLOC_ALIGN_H_
+#define _MALLOC_ALIGN_H_ 1
+
+#include <stdlib.h>
+
+/* Function
+ *
+ * void * malloc_align(size_t size, unsigned int log2_align)
+ *
+ * Description
+ * The malloc_align routine allocates a memory buffer of <size>
+ * bytes aligned to the power of 2 alignment specified by <log2_align>.
+ * For example, malloc_align(4096, 7) will allocate a memory heap
+ * buffer of 4096 bytes aligned on a 128 byte boundary.
+ *
+ * The aligned malloc routine allocates an enlarged buffer
+ * from the standard memory heap. Space for the real allocated memory
+ * pointer is reserved on the front of the memory buffer.
+ *
+ * ----------------- <--- start of allocated memory
+ * | pad 0 to |
+ * |(1<<log2_align)-1|
+ * | bytes |
+ * |-----------------|
+ * | allocation size |
+ * |-----------------|
+ * | real buffer ptr |
+ * |-----------------|<---- returned aligned memory pointer
+ * | |
+ * | requested |
+ * | memory |
+ * | buffer |
+ * | size |
+ * | bytes |
+ * |_________________|
+ *
+ * Memory allocated by this routine must be freed using the free_align
+ * routine.
+ *
+ * The size of the allocation is saved for special cases where the
+ * data must be mored during a realloc_align.
+ */
+
+static __inline void * _malloc_align(size_t size, unsigned int log2_align)
+{
+ void *ret;
+ char *real;
+ unsigned long offset;
+ unsigned long align;
+
+ align = 1 << log2_align;
+ real = (char *)malloc(size + 2*sizeof(void *) + (align-1));
+ if (real) {
+ offset = (align - (unsigned long)(real + 2*sizeof(void *))) & (align-1);
+ ret = (void *)((real + 2*sizeof(void *)) + offset);
+ *((size_t *)(ret)-2) = size;
+ *((void **)(ret)-1) = (void *)(real);
+ } else {
+ ret = (void *)(real);
+ }
+ return (ret);
+}
+
+#endif /* _MALLOC_ALIGN_H_ */
--- /dev/null
+/**************************************************************** \r
+ * Header for the main function\r
+ * Creator: lschor, 2008-11-21\r
+ * Description: Header file for the main function of the PPU\r
+ * \r
+ * Revision: \r
+ * - 2008-11-21: Created\r
+ */\r
+\r
+#ifndef __PPU_MAIN_H__\r
+#define __PPU_MAIN_H__\r
+\r
+// System includes\r
+#include <stdio.h>\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <stdlib.h>\r
+#include <libspe2.h>\r
+#include <pthread.h>\r
+#include <sys/time.h>\r
+\r
+// Local includes\r
+#include "lib/malloc_align.h"\r
+#include "lib/free_align.h"\r
+#include "common.h"\r
+#include "lib/estimation.h"\r
+#include "common_ppu.h"\r
+#include "cbe_mfc.h"\r
+\r
+// Handler for the SPE\r
+extern spe_program_handle_t spu;\r
+\r
+// Program context for the SPEs\r
+volatile parm_context ctx[NUM_SPES] __attribute__ ((aligned(16)));\r
+\r
+// The SPE-program-handler\r
+spe_program_handle_t *program[NUM_SPES];\r
+\r
+// data structure for running SPE thread \r
+typedef struct spu_data {\r
+ spe_context_ptr_t spe_ctx;\r
+ pthread_t pthread;\r
+ void *argp;\r
+} spu_data_t;\r
+\r
+// Data for the SPEs\r
+spu_data_t data[NUM_SPES];\r
+\r
+// Struct which stores a fifo entry temporary\r
+struct fifoEntry {\r
+ uint64_t ea; \r
+ int length;\r
+ int queue;\r
+};\r
+\r
+// Two temporary store elements\r
+struct fifoEntry tmpFifoEntryRead[NUM_SPES]; \r
+struct fifoEntry tmpFifoEntryWrite[NUM_SPES]; \r
+\r
+// Initialize the fifo, we use\r
+const int MAXELEMENT = 262144;\r
+char *locBuf[NUM_FIFO];\r
+int locBufCount[NUM_FIFO]; \r
+int locBufStart[NUM_FIFO]; \r
+\r
+// Mutex-variables for the read/write process of the Queues\r
+pthread_mutex_t mutex [NUM_FIFO];\r
+pthread_mutex_t mutexProcessNr = PTHREAD_MUTEX_INITIALIZER;\r
+\r
+// Number of process that have been finished\r
+int processFinished = 0; \r
+\r
+\r
+#endif\r
--- /dev/null
+/**************************************************************** \r
+ * Main Loop function\r
+ * Creator: lschor, 2008-11-21\r
+ * Description: Includes the main loop function for the ppu_main function\r
+ * \r
+ * Revision: \r
+ * - 2008-11-21: Created\r
+ */\r
+\r
+void workloop()\r
+{\r
+ // Buffer to an address for sending to to the PPE\r
+ volatile char *dataToWriteP __attribute__ ((aligned(128))); \r
+\r
+ // Number of corrent working process\r
+ int processNr; \r
+\r
+ // General variables that have been used in the main workloop\r
+ uint32_t message;\r
+ uint32_t request;\r
+ uint32_t len;\r
+ uint32_t queue;\r
+\r
+ struct timespec t;\r
+ t.tv_sec = 0;\r
+ t.tv_nsec = 5;\r
+\r
+ while (1)\r
+ {\r
+ // Goes through all nodes and check if they like to send some data\r
+ // - Which node has some information\r
+ // - Run through all nodes and if one has some work, do that\r
+ for (processNr = 0; processNr < NUM_SPES; processNr++)\r
+ {\r
+ if (!spe_out_mbox_status(data[processNr].spe_ctx)) continue; \r
+ \r
+ // Get the data\r
+ spe_out_mbox_read(data[processNr].spe_ctx, &message, 1);\r
+ \r
+ request = message >> 28;\r
+ len = (0xffff & message);\r
+ queue = (message >> 16) & 0xfff;\r
+ \r
+ // What type of request are the data? \r
+ if (request == SPE_WRITE_DEMAND) // Want an address to write\r
+ {\r
+\r
+ // If there is not enough space in the queue\r
+ if (MAXELEMENT - locBufCount[queue] < len)\r
+ {\r
+ int message = (0 << 28) | (queue << 16) | locBufCount[queue];\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
+ }\r
+\r
+ // There is enough space in the queue\r
+ else\r
+ {\r
+ #ifdef MEASURE_SPE_WRITE_DEMAND\r
+ struct timeval t_ppe_write_demand_start, t_ppe_write_demand_end;\r
+ gettimeofday(&t_ppe_write_demand_start,NULL);\r
+ #endif\r
+ int message = (1 << 28) | (queue << 16) | len;\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
+\r
+ // Create the memory for the element\r
+ dataToWriteP = (char *)malloc(roundDMA(len));\r
+ \r
+ // Create the address to send\r
+ uint64_t ea;\r
+ ea = (uint64_t)dataToWriteP;\r
+ \r
+ // Enter the information into the temporary Buffer\r
+ tmpFifoEntryWrite[processNr].ea = ea;\r
+ tmpFifoEntryWrite[processNr].length=len;\r
+ tmpFifoEntryWrite[processNr].queue = queue;\r
+ \r
+ // Send the address\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&ea, 2,SPE_MBOX_ANY_NONBLOCKING);\r
+ #ifdef MEASURE_SPE_WRITE_DEMAND\r
+ gettimeofday(&t_ppe_write_demand_end, NULL);\r
+ printf("PPE_WRITE_DEMAND;%f\n",(t_ppe_write_demand_end.tv_sec - t_ppe_write_demand_start.tv_sec) + 0.000001 * (t_ppe_write_demand_end.tv_usec - t_ppe_write_demand_start.tv_usec));\r
+ #endif\r
+ }\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else if (request == SPE_READ_DEMAND) // Want an address to read\r
+ {\r
+ // If no element is in the fifo queue\r
+ if (locBufCount[queue] <= 0)\r
+ {\r
+ int message = (0 << 28) | (queue << 16) | locBufCount[queue];\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
+ }\r
+\r
+ // Has some elements in the fifo queue\r
+ else\r
+ {\r
+ #ifdef MEASURE_SPE_READ_DEMAND\r
+ struct timeval t_ppe_read_demand_start, t_ppe_read_demand_end;\r
+ gettimeofday(&t_ppe_read_demand_start,NULL);\r
+ #endif\r
+\r
+ pthread_mutex_lock( &(mutex[queue]) );\r
+ \r
+ len = len > locBufCount[queue] ? locBufCount[queue] : len;\r
+\r
+ // Can only send special sizes over the DMA\r
+ // 1, 2, 4, 8, 16, ..., 16*x\r
+\r
+ if (len >= 16)\r
+ len = len - (len % 16);\r
+ else if (len >= 8)\r
+ len = 8;\r
+ else if (len >= 4)\r
+ len = 4;\r
+ else if (len >= 2)\r
+ len = 2;\r
+ else\r
+ len = 1;\r
+\r
+ int message = (1 << 28) | (queue << 16) | len;\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);\r
+\r
+ char *buf = (char *)_malloc_align(sizeof(char) * len, 4);\r
+\r
+ // Can directly read all elements from the end of the buffer\r
+ if (locBufStart[queue] + len < MAXELEMENT)\r
+ {\r
+ memcpy(buf, &(locBuf[queue][locBufStart[queue]]), len);\r
+ }\r
+\r
+ // Has to write from the end and from the beginning of the buffer\r
+ else\r
+ {\r
+ memcpy(&(buf[0]), &(locBuf[queue][locBufStart[queue]]), MAXELEMENT - locBufStart[queue]);\r
+ memcpy(&(buf[MAXELEMENT - locBufStart[queue]]), locBuf[queue], len - MAXELEMENT + locBufStart[queue]);\r
+ }\r
+\r
+ locBufCount[queue] -= len;\r
+ locBufStart[queue] = (locBufStart[queue] + len) % MAXELEMENT;\r
+\r
+ pthread_mutex_unlock( & (mutex[queue]) );\r
+\r
+ // Create the address to send\r
+ uint64_t ea;\r
+ ea = (uint64_t)buf;\r
+\r
+ // Enter the information into the temporary Buffer\r
+ tmpFifoEntryRead[processNr].ea = ea;\r
+ tmpFifoEntryRead[processNr].length = len;\r
+ tmpFifoEntryRead[processNr].queue = queue; \r
+\r
+ spe_in_mbox_write(data[processNr].spe_ctx, (uint32_t*)&(tmpFifoEntryRead[processNr].ea), 2,SPE_MBOX_ANY_NONBLOCKING);\r
+ #ifdef MEASURE_SPE_READ_DEMAND\r
+ gettimeofday(&t_ppe_read_demand_end, NULL);\r
+ printf("PPE;%f\n",(t_ppe_read_demand_end.tv_sec - t_ppe_read_demand_start.tv_sec) + 0.000001 * (t_ppe_read_demand_end.tv_usec - t_ppe_read_demand_start.tv_usec));\r
+ #endif\r
+ }\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else if (request == SPE_WRITE_SUC) // Has finished writing\r
+ {\r
+ #ifdef MEASURE_SPE_WRITE_SUC\r
+ struct timeval t_ppe_write_suc_start, t_ppe_write_suc_end;\r
+ gettimeofday(&t_ppe_write_suc_start,NULL);\r
+ #endif\r
+ // Enter the data into the FIFO\r
+ int queueW = tmpFifoEntryWrite[processNr].queue;\r
+ int lenW = tmpFifoEntryWrite[processNr].length; \r
+ char *bufferW = (char *)(tmpFifoEntryWrite[processNr].ea); \r
+ \r
+ pthread_mutex_lock( &(mutex[queueW]) );\r
+\r
+ // Has to write all elements at the beginning or write all elements at the end of the buffer\r
+ if (locBufStart[queueW] + locBufCount[queueW] > MAXELEMENT || locBufStart[queueW] + locBufCount[queueW] + lenW < MAXELEMENT)\r
+ {\r
+ memcpy(&(locBuf[queueW][(locBufStart[queueW] + locBufCount[queueW]) % MAXELEMENT]), bufferW, lenW);\r
+ }\r
+\r
+ // Otherwise something at the end and something at the beginning\r
+ else\r
+ {\r
+ // At the end of the buffer\r
+ memcpy(&(locBuf[queueW][(locBufStart[queueW] + locBufCount[queueW])]), bufferW, MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]);\r
+\r
+ // At the beginning\r
+ memcpy(locBuf[queueW], &(bufferW[MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]]), lenW - (MAXELEMENT - locBufStart[queueW] - locBufCount[queueW]));\r
+ }\r
+\r
+ locBufCount[queueW]+=lenW;\r
+\r
+ pthread_mutex_unlock( & (mutex[queueW]) );\r
+\r
+ // Set the temporary entry to null\r
+ #ifdef MEASURE_SPE_WRITE_SUC\r
+ gettimeofday(&t_ppe_write_suc_end, NULL);\r
+ printf("PPE;%f\n",(t_ppe_write_suc_end.tv_sec - t_ppe_write_suc_start.tv_sec) + 0.000001 * (t_ppe_write_suc_end.tv_usec - t_ppe_write_suc_start.tv_usec));\r
+ #endif\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else if (request == SPE_READ_SUC) // Has finished reading\r
+ {\r
+ #ifdef MEASURE_SPE_READ_SUC\r
+ struct timeval t_ppe_read_suc_start, t_ppe_read_suc_end;\r
+ gettimeofday(&t_ppe_read_suc_start,NULL);\r
+ #endif\r
+ #ifdef MEASURE_SPE_READ_SUC\r
+ gettimeofday(&t_ppe_read_suc_end, NULL);\r
+ printf("PPE;%f\n",(t_ppe_read_suc_end.tv_sec - t_ppe_read_suc_start.tv_sec) + 0.000001 * (t_ppe_read_suc_end.tv_usec - t_ppe_read_suc_start.tv_usec));\r
+ #endif\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else if (request == SPE_DETACH) // A process has finished\r
+ {\r
+ pthread_mutex_lock( &(mutexProcessNr) );\r
+ processFinished++;\r
+ pthread_mutex_unlock( &(mutexProcessNr) );\r
+ }\r
+\r
+ /***************************************************************************************************************/\r
+ else // Did nothing\r
+ {\r
+ nanosleep(&t, NULL);\r
+ }\r
+ }\r
+\r
+ // Check if we can stop the execution\r
+ if (processFinished >= NUM_PROCS) break; \r
+ }\r
+}\r
+\r
--- /dev/null
+/**************************************************************** \r
+ * Process Wrapper file for a PPE process\r
+ * Creator: lschor, 2008-11-21\r
+ * Description: Wrapper for a specific PPE process\r
+ * \r
+ * Revision: \r
+ * - 2008-11-21: Created\r
+ */\r
+\r
+// Include the standard thread functions\r
+#include <pthread.h>\r
+#include <stdio.h>\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <stdlib.h>\r
+\r
+#include "common_ppu.h"\r
+\r
+// Include of the process --> Because all is mapped to one file, each source file is only allow to appear once\r
+//#include "@PROCESSNAME@.c"\r
+\r
+/*\r
+ * The wrapper process\r
+ */\r
+void *@PROCESSNAME@_wrapper( void *ptr )\r
+{\r
+ // Create the wrapper process\r
+ ProcessWrapper *wrapper = (ProcessWrapper *)ptr;\r
+\r
+ //initialize the index array\r
+ int i;\r
+ wrapper->index = (uint32_t *)malloc(4 * sizeof(int));\r
+ for (i = 0; i < 4; i++) \r
+ {\r
+ wrapper->index[i] = getIndex(wrapper->name, "_", i);\r
+ }\r
+\r
+ // DOL process\r
+ DOLProcess* process;\r
+ struct _local_states *state;\r
+\r
+ process = (DOLProcess *)malloc(sizeof(DOLProcess));\r
+ state = (struct _local_states *)malloc(sizeof(struct _local_states));\r
+\r
+ memcpy(process, &@PROCESSNAME@, sizeof(DOLProcess));\r
+ memcpy(state, @PROCESSNAME@.local, sizeof(struct _local_states));\r
+ process->local = state;\r
+ process->wptr = wrapper;\r
+\r
+ // Init the process\r
+ process->init(process);\r
+\r
+ // Run the process\r
+ while (!wrapper->is_detached) \r
+ {\r
+ process->fire(process);\r
+ }\r
+\r
+ // Delete all malloc memory\r
+ free(state); \r
+ free(process); \r
+ free(wrapper->name); \r
+ free(wrapper); \r
+}\r
+\r
+\r
--- /dev/null
+/****************************************************************\r
+ * Process Wrapper file\r
+ * Creator: lschor, 2008-10-30\r
+ * Description: Wrapper for a specific SPE process\r
+ *\r
+ * Revision:\r
+ * - 2008-10-30: Created\r
+ * - 2008-11-08: Update to Double Buffering\r
+ * - 2008-11-15: Added Performance Estimation methods\r
+ */\r
+\r
+// General includes\r
+#include <spu_intrinsics.h>\r
+extern "C" {\r
+ #include <spu_mfcio.h>\r
+}\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <ctype.h>\r
+\r
+// Include to allocate/free using for DMA transfers\r
+#include "lib/malloc_align.h"\r
+#include "lib/free_align.h"\r
+\r
+// Local includes\r
+#include "common.h"\r
+#include "lib/ProcessWrapper.h"\r
+#include "lib/estimation.h"\r
+\r
+// Context file\r
+static parm_context ctx __attribute__ ((aligned (128)));\r
+\r
+// Include of the process\r
+//#include "@PROCESSNAME@.c"\r
+\r
+// Main application\r
+int main(int speid , uint64_t argp)\r
+{\r
+#ifdef MEASURE\r
+ // Start the decrementer for time measurement\r
+ spu_write_decrementer(MEASURE_START);\r
+#endif\r
+\r
+#ifdef MEASURE_SPE\r
+ double t_dol_spe = spu_read_decrementer();\r
+#endif\r
+\r
+ // reserve DMA tag ID\r
+ uint32_t tag_id;\r
+ if((tag_id=mfc_tag_reserve())==MFC_TAG_INVALID){\r
+ printf("SPE: ERROR - can't reserve a tag ID\n"); return 1;\r
+ }\r
+\r
+\r
+ // Get the context information for the whole system\r
+ mfc_get((void*) &ctx, argp, sizeof(ctx), tag_id, 0, 0);\r
+ mfc_write_tag_mask(1<<tag_id);\r
+ mfc_read_tag_status_all();\r
+\r
+ // Create the port / queue structs\r
+ uint32_t port_id[roundDMA(ctx.number_of_ports)] __attribute__ ((aligned (128)));\r
+ uint32_t port_queue_id[roundDMA(ctx.number_of_ports)] __attribute__ ((aligned (128)));\r
+\r
+ // Copy the port list / queue list\r
+ mfc_get((void*)port_id, ctx.port_id, sizeof(uint32_t) * roundDMA(ctx.number_of_ports), tag_id,0,0);\r
+ mfc_get((void*)port_queue_id, ctx.port_queue_id, sizeof(uint32_t) * roundDMA(ctx.number_of_ports), tag_id,0,0);\r
+\r
+\r
+ // Create the wrapper process\r
+ ProcessWrapper *wrapper = (ProcessWrapper *)malloc(sizeof(ProcessWrapper));\r
+ wrapper->number_of_ports = ctx.number_of_ports;\r
+ wrapper->port_id = port_id;\r
+ wrapper->port_queue_id = port_queue_id;\r
+ wrapper->is_detached = 0;\r
+ wrapper->name = (char *)_malloc_align((uint32_t)ctx.processNameLen, 4);\r
+ mfc_get((void *)wrapper->name, ctx.processName, ctx.processNameLen, tag_id, 0, 0);\r
+ waittag(tag_id);\r
+\r
+\r
+ //initialize the index array\r
+ int i;\r
+ wrapper->index = (uint32_t *)malloc(4 * sizeof(int));\r
+ for (i = 0; i < 4; i++)\r
+ {\r
+ wrapper->index[i] = getIndex(wrapper->name, "_", i);\r
+ }\r
+\r
+ // Init the queues for local buffering in the LS\r
+ // Only the queues we really need\r
+ initQueues();\r
+\r
+ // DOL process\r
+ DOLProcess* process;\r
+ struct _local_states *state;\r
+\r
+ process = (DOLProcess *)malloc(sizeof(DOLProcess));\r
+ state = (struct _local_states *)malloc(sizeof(struct _local_states));\r
+\r
+ memcpy(process, &@PROCESSNAME@, sizeof(DOLProcess));\r
+ memcpy(state, @PROCESSNAME@.local, sizeof(struct _local_states));\r
+ process->local = state;\r
+ process->wptr = wrapper;\r
+\r
+ // Init the process\r
+#ifdef MEASURE_DOL_INIT\r
+ double t_dol_init = spu_read_decrementer();\r
+#endif\r
+ process->init(process);\r
+#ifdef MEASURE_DOL_INIT\r
+ t_dol_init -= spu_read_decrementer();\r
+ printf("DOL_INIT;%f\n",t_dol_init * 1 / MEASURE_CPU);\r
+#endif\r
+\r
+ // Run the process\r
+ while (!wrapper->is_detached)\r
+ {\r
+ #ifdef MEASURE_DOL_FIRE\r
+ double t_dol_fire = spu_read_decrementer();\r
+ #endif\r
+\r
+ process->fire(process);\r
+\r
+ #ifdef MEASURE_DOL_FIRE\r
+ t_dol_fire -= spu_read_decrementer();\r
+ printf("DOL_FIRE;%f\n",t_dol_fire * 1 / MEASURE_CPU);\r
+ #endif\r
+ }\r
+\r
+ // Delete all malloc memory\r
+ free(state);\r
+ free(process);\r
+ _free_align(wrapper->name);\r
+ free(wrapper);\r
+\r
+ // release tag ID before exiting\r
+ mfc_tag_release(tag_id);\r
+\r
+\r
+ // Inform the main process that we have finished!\r
+ spu_write_out_mbox((uint32_t)(4));\r
+\r
+#ifdef MEASURE_SPE\r
+ t_dol_spe -= spu_read_decrementer();\r
+ printf("DOL_SPE_@PROCESSNAME@;%f\n",t_dol_spe * 1 / MEASURE_CPU);\r
+#endif\r
+\r
+ return 0;\r
+}\r
+\r
+\r
--- /dev/null
+package dol.visitor.cell;\r
+\r
+import java.io.FileOutputStream;\r
+import java.io.OutputStream;\r
+import java.io.PrintStream;\r
+import java.util.Vector;\r
+\r
+import dol.datamodel.pn.Process;\r
+import dol.datamodel.pn.ProcessNetwork;\r
+import dol.visitor.PNVisitor;\r
+\r
+/**\r
+ * This class is a class for a visitor that is used to generate the build file\r
+ * for the Application on the CBE (i.e. a bash file for the cell\r
+ * \r
+ * @author lschor, 2008-10-30\r
+ * \r
+ * Revision: \r
+ * 2008-10-30: Updated the file for the CBE\r
+ * 2008-11-08: Add double buffering\r
+ */\r
+public class CellBuildFileVisitor extends PNVisitor {\r
+\r
+ /**\r
+ * Constructor.\r
+ * \r
+ * @param dir\r
+ * path of the Makefile\r
+ */\r
+ public CellBuildFileVisitor(String dir) {\r
+ _dir = dir;\r
+ }\r
+\r
+ /**\r
+ * Create a Makefile for the given process network.\r
+ * \r
+ * @param pn\r
+ * process network\r
+ */\r
+ public void visitComponent(ProcessNetwork pn) {\r
+ try {\r
+ String filename = _dir + _delimiter + "pncbe.sh";\r
+ OutputStream file = new FileOutputStream(filename);\r
+ PrintStream ps = new PrintStream(file);\r
+\r
+ // General information / notes and commands\r
+ ps.println("#!/bin/bash");\r
+ ps.println("clear");\r
+ ps.println();\r
+ ps\r
+ .println("# Bash file to run the DOL application on the Cell processor");\r
+ ps\r
+ .println("# Start the Cell-Simulator and enter the following commands: ");\r
+ ps\r
+ .println("# callthru source <Absolute path to the folder of this file>/pncbe.sh > pncbe.sh");\r
+ ps\r
+ .println("# for example: callthru source /opt/cell/sdk/src/tutorial/pn_test/pncbe.sh > pncbe.sh");\r
+ ps.println("# chmod +x pncbe.sh");\r
+ ps.println();\r
+ ps\r
+ .println("# To run the DOL application, use the following command: ");\r
+ ps.println("# ./pncbe.sh");\r
+ ps.println();\r
+ ps.println("# Folder in which the application is stored");\r
+ ps.println("FOLDER=/opt/cell/sdk/src/tutorial/pn_test");\r
+ ps.println();\r
+\r
+ // Go through each process and copy its data to the Cell\r
+ String subdirectory = "";\r
+ String applicationName = "";\r
+ Vector<String> pList = new Vector<String>();\r
+\r
+ for (Process process : pn.getProcessList()) {\r
+ String basename = process.getBasename();\r
+ if (!pList.contains(basename) && process.getNumOfInports() > 0 && process.getNumOfOutports() > 0) {\r
+ subdirectory = "spu_" + basename;\r
+ applicationName = subdirectory + "/spu_"\r
+ + basename + "_wrapper";\r
+\r
+ ps.println("# " + basename);\r
+ ps.println("if [ ! -d " + subdirectory + " ]; then");\r
+ ps.println(" mkdir " + subdirectory);\r
+ ps.println("fi;");\r
+ ps.println("callthru source $FOLDER/" + applicationName\r
+ + " > " + applicationName);\r
+ ps.println("chmod +x " + applicationName);\r
+ ps.println();\r
+ pList.add(basename);\r
+ }\r
+ }\r
+\r
+ // Load also the main application to the CBE\r
+ ps.println("# Main program");\r
+ ps.println("callthru source $FOLDER/ppu_main > ppu_main");\r
+ ps.println("chmod +x ppu_main");\r
+ ps.println();\r
+\r
+ // Run the main program\r
+ ps.println("# run the main program");\r
+ ps.println("./ppu_main");\r
+ } catch (Exception e) {\r
+ System.out.println("CbeMakefileVisitor: exception occured: "\r
+ + e.getMessage());\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ protected String _dir = null;\r
+\r
+}\r
--- /dev/null
+package dol.visitor.cell;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+
+/**
+ * This class is a class for a constant file
+ *
+ * @author lschor, 2008-11-08
+ *
+ * Revision:
+ * 2008-11-08: Created
+ */
+public class CellConstantVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of this file
+ */
+ public CellConstantVisitor(String dir, CellMapping mapping) {
+ _dir = dir;
+ _mapping = mapping;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ _ui = UserInterface.getInstance();
+ String filename = _dir + _delimiter + "lib" + _delimiter + "constant.h";
+ OutputStream file = new FileOutputStream(filename);
+ _mainPS = new CodePrintStream(file);
+
+ int numSpes = 0;
+
+ for (Process p : x.getProcessList()) {
+ if (p.getNumOfInports() > 0 && p.getNumOfOutports() > 0)
+ numSpes++;
+ }
+
+ //create header section
+ _mainPS.println("// ========================");
+ _mainPS.println("// constant.h file");
+ _mainPS.println("// ========================");
+
+ // Includes
+ _mainPS.println("#include <stdio.h>");
+
+ // Define the number of FIFO queues and the number of processes
+ _mainPS.println("#ifndef _CONSTANT_H_");
+ _mainPS.println("#define _CONSTANT_H_");
+ _mainPS.println("");
+ _mainPS.println("#define NUM_PROCS " + x.getProcessList().size()
+ + " // total number of processes");
+ _mainPS.println("#define NUM_PROCS_SPU " + _mapping.getNrSPUProcess()
+ + " // number of processes to map on the SPU");
+ _mainPS.println("#define NUM_PROCS_PPU " + _mapping.getNrPPUProcess()
+ + " // number of processes to map to the PPU");
+ _mainPS.println("#define NUM_SPES " + _mapping.getNrSPE()
+ + " // number of SPE's to be used (PS3 = 6)");
+ _mainPS.println("#define NUM_FIFO " + x.getChannelList().size()
+ + " // number of FIFOs we use");
+ _mainPS.println("#define FIFO_SIZE_FACTOR 10 "
+ + " // factor to increase the IN-Channels of the PPE");
+ _mainPS.println("#define ALIGNMENT_FACTOR 7 "
+ + " // alignment factor for the DMA transfers (at least 4, "
+ + "7 for optimal performance)");
+ _mainPS.println("#define ALIGNMENT_FACTOR_POWER2 128");
+ _mainPS.println("#define BLOCKED_MAX_NR 5 "
+ + " // number of times a process should wait until "
+ + "resending a request");
+ _mainPS.println("#define STORE_REQUESTS "
+ + " // defines if one would like to store requests which"
+ + "cannot be worked out currently (see also FastCommunication.cpp)");
+ _mainPS.println("");
+ _mainPS.print("static unsigned long int FIFO_SIZE[NUM_FIFO] = {");
+ for (int indx = 0; indx < x.getChannelList().size(); indx++) {
+ int size = x.getChannelList().elementAt(indx).getSize();
+ if (x.getChannelList().elementAt(indx).getTokenSize() != 0) {
+ size *= x.getChannelList().elementAt(indx).getTokenSize();
+ }
+ if(indx == x.getChannelList().size() - 1) {
+ _mainPS.print(size);
+ } else {
+ _mainPS.print(size + ", ");
+ }
+ }
+
+ _mainPS.println("}; // Size of the FIFOs");
+ _mainPS.println("");
+ _mainPS.println("#endif // _CONSTANT_H_ ");
+ }
+ catch (Exception e) {
+ System.out.println("CellModuleVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param x process that needs to be processed
+ */
+ public void visitComponent(Process x) {
+ }
+
+ /**
+ *
+ * @param x channel that needs to be processed
+ */
+ public void visitComponent(Channel x) {
+ }
+
+ protected CellMapping _mapping;
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+}
--- /dev/null
+package dol.visitor.cell;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Configuration;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate a CBE package
+ * Makefile.
+ */
+public class CellMakefileVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir
+ * path of the Makefile
+ */
+ public CellMakefileVisitor(String dir, CellMapping mapping) {
+ _dir = dir;
+ _mapping = mapping;
+ }
+
+ /**
+ * Create a Makefile for the given process network.
+ *
+ * @param pn
+ * process network
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ String filename = _dir + _delimiter + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ ps.println("####################");
+ ps.println("# Main Makefile for the DOL application on the CBE");
+ ps.println("####################");
+ ps.println();
+ ps.println("# Subdirectories");
+
+
+ // Subdirectories of baseprocesses on the SPU
+ String subdirectories = "";
+ Vector<String> pList = new Vector<String>();
+ for (Process process : _mapping.getAllSpuBaseProcess()) {
+ String basename = process.getBasename();
+ subdirectories += "spu_" + basename + " ";
+ }
+
+ // Directory for the SPU OS'es (only if there are really processes on the SPE!
+ if (_mapping.getNrSPUProcess() > 0)
+ subdirectories += "spu";
+
+ String srcdirectories = "";
+
+ // Subdirectory of baseprocesses on the PPU
+ for (Process process : _mapping.getAllPPUBaseProcess()) {
+ String basename = process.getBasename();
+ srcdirectories += " $(wildcard ppu_" + basename + "/*.cpp)";
+ }
+
+ // Directory for the PPU OS'es
+ srcdirectories += " $(wildcard ppu/*.cpp)";
+
+ String linkList = "";
+ String srcList = "";
+ for (Process process : _mapping.getAllPPUBaseProcess()) {
+ String basename = process.getBasename();
+ linkList += "ppu_" + basename + "/ppu_" + basename + ".o ";
+ srcList += "$(wildcard ppu_" + basename + "/*.cpp) ";
+ }
+ pList.clear();
+
+ ps.println("DIRS := " + subdirectories);
+ ps.println("");
+
+ ps.println("# General definitions:");
+ ps.println("CC = ppu-g++");
+ ps.println("CCFLAGS = -ftree-vectorize -O3 -maltivec -funroll-loops -mabi=altivec -mcpu=cell");
+ ps.println("COMPILE = $(CC) $(CCFLAGS) -c");
+ ps.print("LINK = $(CC) -lspe2 -lpthread ");
+ for (Configuration conf : pn.getCfgList()) {
+ if (conf.getName().equals("DYNAMIC_LINK"))
+ ps.print(conf.getValue() + " ");
+ }
+ ps.println("");
+
+ ps.println("CBE_INCLUDE = /opt/cell/sdk/usr/include");
+ ps.println("LIB_INC = -I lib -I lib/ppu -I lib/pt -I . -I $(CBE_INCLUDE)");
+ ps.println("RM = rm");
+ ps.println("ECHO = echo");
+ ps.println("EXE = sc_application");
+ ps.println("");
+ ps.println("src := $(wildcard lib/ppu/*.cpp) $(wildcard *.cpp)" + srcdirectories);
+ ps.println("srcAll := $(wildcard lib/ppu/*.cpp) $(wildcard *.cpp) " + srcList);
+ ps.println("srcspu := $(wildcard lib/spu/*.cpp) ");
+ ps.println("obj = $(src:.cpp=.o)");
+ ps.println("objspu = $(srcspu:.cpp=.o)");
+ ps.println("");
+ ps.println("$(EXE): $(obj) $(srcAll)");
+ ps.println("\tfor d in $(DIRS); do (cd $$d; $(MAKE) ); done");
+ ps.println("\t$(LINK) -o $(EXE) $(obj)");
+ ps.println("");
+ ps.println("%.o :");
+ ps.println("\t$(COMPILE) -o $(*D)/$(*F).o $(*D)/$(*F).cpp $(LIB_INC)");
+ ps.println("");
+ ps.println("clean:");
+ ps.println("\tfor d in $(DIRS); do (cd $$d; $(MAKE) clean ); done");
+ ps.println("\trm $(objspu)");
+ ps.println("\trm $(obj) ");
+ ps.println("\trm $(EXE)");
+ ps.println("");
+
+ } catch (Exception e) {
+ System.out.println("CbeMakefileVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ protected CellMapping _mapping;
+}
--- /dev/null
+package dol.visitor.cell;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.mapping.ComputationBinding;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.main.UserInterface;
+import dol.parser.xml.archischema.ArchiXmlParser;
+import dol.parser.xml.mapschema.MapXmlParser;
+
+public class CellMapping {
+
+ /**
+ * Constructor
+ * @param pn
+ */
+ CellMapping(ProcessNetwork pn, String mapping, boolean ppu, int nrSPU) {
+ _pn = pn;
+
+ _maxSPU = nrSPU;
+
+ // Select the mapping
+
+ // Structural mapping
+ if (mapping.compareTo("structural") == 0) {
+ System.out.println("Cell: use structural mapping");
+ structuralMapping(pn, ppu);
+ }
+
+ // Random mapping
+ else if (mapping.compareTo("random") == 0) {
+ System.out.println("Cell: use random mapping");
+ randomMapping(pn, ppu);
+ }
+
+ // Predefined
+ else if (mapping.compareTo("predefined") == 0) {
+ System.out.println("Cell: Use predefined mapping.");
+ System.out.println(" All other parameters are ignored.");
+ predefinedMapping(pn);
+
+ _maxSPU = _SPUList.size();
+ ppu = this._PPU.size() == 0 ? false : true;
+ }
+
+ // All to PPU
+ else if (mapping.compareTo("ppu") == 0) {
+ System.out.println("Cell: Map all processes to the PPU");
+ allPPUMapping(pn);
+ }
+
+ // Default mapping
+ else {
+ System.out.println("WARNING: Cell: use default mapping");
+ structuralMapping(pn, ppu);
+ }
+
+ System.out.println("Cell: Nr of SPE is " + _maxSPU);
+
+ if (ppu) {
+ System.out.println("Cell: Mapped some processes to the PPE");
+ }
+ }
+
+ /**
+ * Returns a list which process is mapped to which spu
+ *
+ * @return the process list
+ */
+ public ArrayList<Vector<Process>> getSPUList() {
+ return _SPUList;
+ }
+
+ /**
+ * Returns list of all processes which are mapped to an spu
+ */
+ public Vector<Process> getAllSpuProcess() {
+ Vector<Process> processList = new Vector<Process>();
+
+ for (Vector<Process> spu : _SPUList) {
+ for (Process p : spu) {
+ processList.add(p);
+ }
+ }
+ return processList;
+ }
+
+ /**
+ * Returns a list of all base processes which occur on the spu's
+ */
+ public Vector<Process> getAllSpuBaseProcess() {
+ Vector<Process> pList = new Vector<Process>();
+ Vector<String> pListName = new Vector<String>();
+ for (Process process : getAllSpuProcess()) {
+ String basename = process.getBasename();
+ if (!pListName.contains(basename)) {
+ pList.add(process);
+ pListName.add(basename);
+ }
+ }
+ return pList;
+ }
+
+ /**
+ * Returns a list of all processes which are mapped to the ppu
+ */
+ public Vector<Process> getPPU() {
+ return _PPU;
+ }
+
+ /**
+ * Returns a list of all base processes which occur on the ppu
+ */
+ public Vector<Process> getAllPPUBaseProcess() {
+ Vector<Process> pList = new Vector<Process>();
+ Vector<String> pListName = new Vector<String>();
+ for (Process process : _PPU) {
+ String basename = process.getBasename();
+ if (!pListName.contains(basename)) {
+ pList.add(process);
+ pListName.add(basename);
+ }
+ }
+ return pList;
+ }
+
+ /**
+ * Return the number of processes which are mapped to the ppu
+ */
+ public int getNrPPUProcess() {
+ return _PPU.size();
+ }
+
+ /**
+ * Returns the number of processes which are mapped to the SPU
+ */
+ public int getNrSPUProcess() {
+ return getAllSpuProcess().size();
+ }
+
+ /**
+ * Returns the number of SPU which are used
+ */
+ public int getNrSPE() {
+ return _SPUList.size();
+ }
+
+ /**
+ * Performs a random mapping of the processes
+ *
+ * @param x
+ * the process network
+ * @param ppu_choose
+ * true if the sinks and sources should be mapped to the PPU
+ */
+ protected void randomMapping(ProcessNetwork x, boolean ppu_choose) {
+ ArrayList<Vector<Process>> spu = new ArrayList<Vector<Process>>();
+ Vector<Process> ppu = new Vector<Process>();
+
+ int addSPU = 0;
+ for (Process p : x.getProcessList()) {
+ // A process to map to the PPU
+ if ((p.getNumOfInports() == 0 || p.getNumOfOutports() == 0)
+ && ppu_choose) {
+ ppu.add(p);
+ }
+
+ // A process to map to the SPU
+ else {
+ // As long as there is a free SPU, add the process to this SPU
+ if (addSPU < _maxSPU) {
+ Vector<Process> pList = new Vector<Process>();
+ pList.add(p);
+ spu.add(pList);
+ }
+
+ // Have to add the process to an already used SPU
+ else {
+ spu.get(addSPU % _maxSPU).add(p);
+ }
+
+ addSPU++;
+ }
+ }
+
+ _SPUList = spu;
+ _PPU = ppu;
+ }
+
+ /**
+ * Performs a structural mapping of the processes. That means that the
+ * function tries to keep the structural order of the process network. The
+ * order is given depending on the occurrence of the process in the
+ * structure file.
+ *
+ * @param x
+ * the process network
+ * @param ppu_choose
+ * true if the sinks and sources should be mapped to the PPU
+ */
+ protected void structuralMapping(ProcessNetwork x, boolean ppu_choose) {
+ ArrayList<Vector<Process>> spu = new ArrayList<Vector<Process>>();
+ Vector<Process> ppu = new Vector<Process>();
+
+ Vector<Process> spu_temp = new Vector<Process>();
+
+ // Each process is allocated to the PPE or the SPE (as general)
+ for (Process p : x.getProcessList()) {
+ // A process to map to the PPU
+ if ((p.getNumOfInports() == 0 || p.getNumOfOutports() == 0)
+ && ppu_choose) {
+ ppu.add(p);
+ }
+
+ // A process to map to the SPU
+ else {
+ spu_temp.add(p);
+ }
+ }
+
+ System.out.println("Total processes: " + spu_temp.size());
+
+ // Do the structural mapping for all the SPE processes
+ int nrSPUProcess = spu_temp.size();
+ for (int i = 0; i < _maxSPU; i++) {
+
+ if (spu_temp.size() <= 0)
+ break;
+
+ Vector<Process> pList = new Vector<Process>();
+ for (int j = 0; j < Math.ceil(((double) (nrSPUProcess - i))
+ / _maxSPU); j++) {
+ pList.add(spu_temp.remove(0));
+ }
+
+ spu.add(pList);
+ }
+
+ System.out.println("End Total processes: " + spu_temp.size());
+
+ _SPUList = spu;
+ _PPU = ppu;
+ }
+
+ /**
+ * Maps the processes depending on the architectural and mapping files
+ *
+ * @param x
+ */
+ protected void predefinedMapping(ProcessNetwork x) {
+ // The SPUs
+ ArrayList<Vector<Process>> spu = new ArrayList<Vector<Process>>();
+
+ // The PPU
+ Vector<Process> ppu = new Vector<Process>();
+
+ ArchiXmlParser archParser = new ArchiXmlParser();
+ //System.out.println(_ui.getPlatformFileName());
+ Architecture arch = archParser.doParse(_ui.getPlatformFileName());
+ MapXmlParser mappingParser = new MapXmlParser(x, arch);
+ Mapping mapping = mappingParser.doParse(_ui.getMappingFileName());
+
+ // Go through all process and check where to add
+ for (Process p : x.getProcessList()) {
+ for (ComputationBinding b : mapping.getCompBindList()) {
+ if (b.getProcess().getName().equals(p.getName())) {
+ // Mapping to PPU
+ if (b.getProcessor().getName().equals("ppu")) {
+ System.out.println("Mapped process " + p.getName()
+ + " to the PPU");
+ ppu.add(p);
+ }
+ // Maps to one of the SPU, they are written in the format
+ // spu_0, spu_1, ...
+ else {
+ int index = Integer.valueOf(b.getProcessor()
+ .getName().replaceAll(".*_", ""));
+
+ while (spu.size() <= index) {
+ Vector<Process> spu_temp = new Vector<Process>();
+ spu.add(spu_temp);
+ }
+
+ spu.get(index).add(p);
+ System.out.println("Mapped process " + p.getName()
+ + " to the SPU_" + index);
+ }
+ }
+ }
+ }
+
+ _SPUList = spu;
+ _PPU = ppu;
+ }
+
+
+ /**
+ * Performs a mapping of all processes to the PPU.
+ *
+ * @param x the process network
+ */
+ protected void allPPUMapping(ProcessNetwork x) {
+ ArrayList<Vector<Process>> spu = new ArrayList<Vector<Process>>();
+ Vector<Process> ppu = new Vector<Process>();
+
+ // Each process is allocated to the PPE or the SPE (as general)
+ for (Process p : x.getProcessList()) {
+ ppu.add(p);
+ }
+
+ _SPUList = spu;
+ _PPU = ppu;
+ }
+
+ protected ArrayList<Vector<Process>> _SPUList = null;
+ protected Vector<Process> _PPU = null;
+ protected ProcessNetwork _pn;
+ protected int _maxSPU = 6;
+ protected UserInterface _ui = UserInterface.getInstance();
+}
--- /dev/null
+package dol.visitor.cell;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Vector;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+
+/**
+ * This class is a class for a visitor that is used to generate the main
+ * program.
+ *
+ * @author lschor, 2008-10-30
+ *
+ * Remarks: Based on a original file from khuang for rtems
+ *
+ * Revision: 2008-10-30: Updated the file for the CBE 2008-11-08: Add
+ * double buffering 2008-11-16: Add new fifo implementation and defines
+ * for measurement 2008-11-21: Sink/Source do not run on the SPE, but on
+ * the PPE (as Linux thread) 2009-03-17: Added Protothread Support
+ * 2009-04-07: Several modifications, so that one only writes if there
+ * is enough memory, do not allocate all queues on PPU
+ */
+public class CellModuleVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir
+ * path of this file
+ */
+ public CellModuleVisitor(String dir, HashMap<Port, Integer> portMap,
+ CellMapping mapping) {
+ _dir = dir;
+ _portMap = portMap;
+ _mapping = mapping;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param x
+ * process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ // Create in a first step the different SPU OS Layers
+ ArrayList<Vector<Process>> spuList = _mapping.getSPUList();
+ Vector<Process> ppu = _mapping.getPPU();
+
+ // Create the main file for the PPU
+ _ui = UserInterface.getInstance();
+ String filename = _dir + _delimiter + "ppu_main.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ _mainPS = new CodePrintStream(file);
+
+ // create header section
+ _mainPS.println("// ========================");
+ _mainPS.println("// ppu_main.cpp file");
+ _mainPS.println("// ========================");
+ _mainPS.println("");
+
+ // Includes
+ _mainPS.println("#include \"ppu_main.h\"");
+ _mainPS.println("");
+
+ // Function to create and run one SPE thread
+ _mainPS.println("// create and run one SPE thread");
+ _mainPS.println("void *spu_pthread(void *arg) {");
+ _mainPS.println(" spu_data_t *datp = (spu_data_t *)arg;");
+ _mainPS.println(" uint32_t entry = SPE_DEFAULT_ENTRY;");
+ _mainPS.println(" printf(\")PPE: spe thread start run\\n\" );");
+ _mainPS.println(" if(spe_context_run(datp->spe_ctx,&entry,0,datp->argp,NULL,NULL)<0){");
+ _mainPS.println(" perror (\"Failed running context\"); exit (1);");
+ _mainPS.println(" }");
+ _mainPS.println(" printf(\")PPE: spe thread finish run\\n\");");
+ _mainPS.println(" pthread_exit(NULL);");
+ _mainPS.println("}");
+ _mainPS.println("");
+
+ // Declaration of the Header function for the PPE-Wrappers
+ /*
+ * for (Process p : ppu) { _mainPS.println("void *"+ p.getBasename()
+ * + "_wrapper( void *ptr );"); }
+ */
+ _mainPS.println("void *ppu( void *ptr );");
+ _mainPS.println();
+
+ // Create the port_id and the port_queue_id arrays to send over the
+ // DMA
+ for (Process process : _mapping.getAllSpuProcess()) {
+ String processName = process.getName();
+ _mainPS.println("volatile char " + processName
+ + "_name[256] __attribute__ ((aligned(16)));");
+ }
+ _mainPS.println();
+
+ // Go through all SPEs
+ for (Vector<Process> spu : spuList) {
+ _mainPS.println("volatile uint64_t spu_"
+ + spuList.indexOf(spu) + "[" + spu.size()
+ + "] __attribute__ ((aligned(16)));");
+ }
+ _mainPS.println();
+ _mainPS.println("// The input queue of a process is always on the SPU of the receiver, negative means that the queue is on the PPE");
+ _mainPS.println("volatile int32_t queueOnSPU [NUM_FIFO] __attribute__ ((aligned(16)));");
+ _mainPS.println();
+ _mainPS.println(" // The queue comes from this SPU");
+ _mainPS.println("volatile int32_t queueFromSPU [NUM_FIFO] __attribute__ ((aligned(16)));");
+ _mainPS.println();
+ _mainPS.println(" volatile uint64_t ea_ls_base[NUM_SPES] __attribute__ ((aligned(16)));");
+ _mainPS.println("volatile uint64_t context_addr[NUM_SPES] __attribute__ ((aligned(16)));");
+ _mainPS.println("volatile spe_spu_control_area_t* mfc_ctl[NUM_SPES] __attribute__ ((aligned(16)));");
+ _mainPS.println("volatile uint64_t fifoTails[NUM_FIFO] __attribute__ ((aligned(16)));");
+ _mainPS.println();
+
+ // Create the main function
+ _mainPS.println("int main()");
+ _mainPS.println("{");
+
+ // List with all SPU to be open
+ _mainPS.println(" char spe_names[NUM_SPES][60] = {");
+ for (Vector<Process> spu : spuList) {
+ _mainPS.println(" \"spu/spu_os_" + spuList.indexOf(spu)
+ + "\",");
+ }
+ _mainPS.println(" };");
+
+ _mainPS.println();
+
+ for (Channel c : x.getChannelList()) {
+ // Search for the origin spe
+ int origin = -1;
+
+ for (Vector<Process> spu : spuList) {
+
+ if (spu.contains(c.getOrigin())) {
+ origin = spuList.indexOf(spu);
+ break;
+ }
+ }
+
+ // Origin on the PPU
+ if (origin == -1) {
+ origin = (-1) * (ppu.indexOf(c.getOrigin()) + 1);
+ }
+
+ _mainPS.println(" queueFromSPU["
+ + x.getChannelList().indexOf(c) + "] = " + origin
+ + ";");
+ }
+
+ _mainPS.println();
+
+ for (Channel c : x.getChannelList()) {
+ // Search for the origin spe
+ int origin = -1;
+
+ for (Vector<Process> spu : spuList) {
+ if (spu.contains(c.getTarget())) {
+ origin = spuList.indexOf(spu);
+ break;
+ }
+ }
+
+ // Origin on the PPU
+ if (origin == -1) {
+ origin = (-1) * (ppu.indexOf(c.getTarget()) + 1);
+ }
+
+ _mainPS.println(" queueOnSPU["
+ + x.getChannelList().indexOf(c) + "] = " + origin
+ + ";");
+ }
+
+ _mainPS.println();
+
+ // connect ports to channels
+ HashMap<Channel, Integer> channel_map = new HashMap<Channel, Integer>();
+
+ int j = 0;
+ for (Channel c : x.getChannelList()) {
+ channel_map.put(c, j++);
+ }
+
+ // Add to each process the ports and the queues
+ _mainPS
+ .println(" //Add to each process the ports and the queues");
+ j = 0;
+
+ // SPU Process
+ for (Process process : _mapping.getAllSpuProcess()) {
+ String processName = process.getName();
+ _mainPS.println(" ctx_proc[" + j + "]"
+ + ".is_detached = 0;");
+ _mainPS.println(" strcpy((char *)" + processName
+ + "_name, " + "\"" + processName + "\");");
+ _mainPS.println(" ctx_proc[" + j + "]"
+ + ".processName = (uint64_t) " + processName
+ + "_name;");
+ _mainPS.println(" ctx_proc[" + j + "]"
+ + ".processNameLen = ((strlen((char *)"
+ + processName + "_name) + 15) & ~15);");
+ _mainPS.println();
+ j++;
+ }
+
+ _mainPS.println(" // Mapping tasks -> What to map to which SPE?");
+ _mainPS.println(" // Example: Square 0-2 to SPE 0 AND Square 3-5 to SPE 1");
+ j = 0;
+ for (Process process : _mapping.getAllSpuProcess()) {
+ for (Vector<Process> spu : spuList) {
+ if (spu.contains(process)) {
+ _mainPS.println(" spu_" + spuList.indexOf(spu)
+ + "[" + spu.indexOf(process)
+ + "] = (uint64_t) &(ctx_proc[" + j
+ + "]);");
+ j++;
+ break;
+ }
+ }
+ }
+
+ for (Vector<Process> spu : spuList) {
+ _mainPS.println(" ctx_spu[" + spuList.indexOf(spu)
+ + "].procContents = (uint64_t) spu_"
+ + spuList.indexOf(spu) + ";");
+ _mainPS.println(" ctx_spu[" + spuList.indexOf(spu)
+ + "].procContentsLen = " + spu.size() + ";");
+ }
+
+ _mainPS.println();
+
+ // Init the SPE control structure
+ _mainPS.println(" //Initiate SPEs control structure");
+ _mainPS.println(" int num = 0; ");
+ _mainPS.println(" for( num=0; num<NUM_SPES; num++){");
+ _mainPS.println(" data[num].argp = (void *)&(ctx_spu[num]);");
+ _mainPS.println(" }");
+ _mainPS.println();
+
+ _mainPS.println(" // Loop on all SPEs and for each perform three steps:");
+ _mainPS.println(" // - create SPE context");
+ _mainPS.println(" // - open images of SPE programs into main storage");
+ _mainPS.println(" // <spe_names> variable store the executable name");
+ _mainPS.println(" // - Load SPEs objects into SPE context local store");
+ _mainPS.println(" for( num=0; num<NUM_SPES; num++){");
+ _mainPS.println(" if ((data[num].spe_ctx = spe_context_create (SPE_MAP_PS, NULL)) == NULL) {");
+ _mainPS.println(" perror(\"Failed creating context\"); exit(1);");
+ _mainPS.println(" }");
+ _mainPS.println(" if (!(program[num] = spe_image_open(&spe_names[num][0]))) {");
+ _mainPS.println(" perror(\"Fail opening image\"); exit(1);");
+ _mainPS.println(" }");
+ _mainPS.println(" if (spe_program_load ( data[num].spe_ctx, program[num])) {");
+ _mainPS.println(" perror(\"Failed loading program\"); exit(1);");
+ _mainPS.println(" } ");
+ _mainPS.println(" }");
+ _mainPS.println("");
+
+ _mainPS.println(" // update the parameters of each SPE");
+ _mainPS.println(" for( num=0; num<NUM_SPES; num++){");
+ _mainPS.println(" if( (ea_ls_base[num] = (uint64_t)(spe_ls_area_get(data[num].spe_ctx))) == 0) {");
+ _mainPS.println(" perror(\"Failed map LS to main storage\"); exit(1);");
+ _mainPS.println(" }");
+ _mainPS.println(" ctx_spu[num].ea_base = ea_ls_base[num];");
+ _mainPS.println(" context_addr[num] = (uint64_t)data[num].spe_ctx;");
+ _mainPS.println(" }");
+
+ _mainPS.println(" for (num=0; num<NUM_SPES; num++) {");
+ _mainPS.println(" if ((mfc_ctl[num] = (spe_spu_control_area_t*) spe_ps_area_get(data[num].spe_ctx, SPE_CONTROL_AREA))==NULL){");
+ _mainPS.println(" perror(\"Failed mapping MFC control area\"); exit(1);");
+ _mainPS.println(" }");
+ _mainPS.println(" }");
+ _mainPS.println(" ");
+
+ _mainPS.println(" for (num=0; num<NUM_SPES; num++) {");
+ _mainPS.println(" ctx_spu[num].queueFromSPU = (uint64_t) queueFromSPU;");
+ _mainPS.println(" ctx_spu[num].queueOnSPU = (uint64_t) queueOnSPU;");
+ _mainPS.println(" ctx_spu[num].procContentsAll = (uint64_t) mfc_ctl;");
+ _mainPS.println(" ctx_spu[num].fifoTails = (uint64_t) fifoTails;");
+ _mainPS.println(" }");
+ _mainPS.println("");
+ _mainPS.println("// This is the PPU");
+ _mainPS.println(" ProcessData *ppu_Process_Wrapper = (ProcessData *)malloc(sizeof(ProcessData));");
+ _mainPS.println(" ppu_Process_Wrapper->procContentsAll = (uint64_t *) context_addr;");
+ _mainPS.println(" ppu_Process_Wrapper->queueFromSPU = (int32_t *)queueFromSPU;");
+ _mainPS.println(" ppu_Process_Wrapper->queueOnSPU = (int32_t *)queueOnSPU;");
+ _mainPS.println(" ppu_Process_Wrapper->ea_ls_base = (uint64_t *)ea_ls_base;");
+ _mainPS.println(" ppu_Process_Wrapper->fifoTails = (uint64_t *) fifoTails;");
+ _mainPS.println(" ");
+
+ _mainPS.println(" // create SPE pthreads");
+ _mainPS.println(" for( num=0; num<NUM_SPES; num++){");
+ _mainPS.println(" if(pthread_create(&data[num].pthread,NULL,&spu_pthread, &data[num])){");
+ _mainPS.println(" perror(\"Failed creating thread\"); exit(1);");
+ _mainPS.println(" }");
+ _mainPS.println(" }");
+ _mainPS.println(" ");
+ _mainPS.println(" // create PPE pthreads");
+ _mainPS.println(" pthread_t thread_ppu;");
+ _mainPS.println(" pthread_create( &thread_ppu, NULL, ppu, ppu_Process_Wrapper);");
+ _mainPS.println(" ");
+
+ _mainPS.println();
+ _mainPS.println(" // Loop on all SPEs and for each perform two steps:");
+ _mainPS.println(" // - wait for all the SPE pthread to complete");
+ _mainPS.println(" // - destroy the SPE contexts");
+ _mainPS.println(" for( num=0; num<NUM_SPES; num++){");
+ _mainPS.println(" if(pthread_join (data[num].pthread, NULL)) {");
+ _mainPS.println(" perror(\"Failed joining thread\"); exit (1);");
+ _mainPS.println(" }");
+ _mainPS.println(" ");
+ _mainPS.println(" if (spe_context_destroy( data[num].spe_ctx )) {");
+ _mainPS.println(" perror(\"Failed spe_context_destroy\"); exit(1);");
+ _mainPS.println(" }");
+ _mainPS.println(" }");
+ _mainPS.println(" ");
+ _mainPS.println(" // Join with PPU");
+ _mainPS.println(" if(pthread_join (thread_ppu, NULL)) {");
+ _mainPS.println(" perror(\"Failed joining thread\"); exit (1);");
+ _mainPS.println(" }");
+ _mainPS.println(" ");
+ _mainPS.println(" printf(\")PPE:) Complete running all super-fast SPEs and PPE\\n\");");
+ _mainPS.println("");
+
+ _mainPS.println(" return (0);");
+ _mainPS.println("}");
+ } catch (Exception e) {
+ System.out.println("CellModuleVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param x
+ * process that needs to be processed
+ */
+ public void visitComponent(Process x) {
+ }
+
+ /**
+ *
+ * @param x
+ * channel that needs to be processed
+ */
+ public void visitComponent(Channel x) {
+ }
+
+ /**
+ * Round the parameter to the next DMA-number up. Example: 23 gives 32.
+ *
+ * @param number
+ * number to round up
+ * @return next DMA-number
+ */
+ protected int roundDMA(int number) {
+ if (number > 16)
+ return number + 16 - (number % 16);
+ else if (number > 8)
+ return 16;
+ else if (number > 4)
+ return 8;
+ else if (number > 2)
+ return 4;
+ else if (number > 1)
+ return 2;
+ else
+ return 1;
+ }
+
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected HashMap<Port, Integer> _portMap;
+ protected CellMapping _mapping;
+
+}
--- /dev/null
+package dol.visitor.cell;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+public class CellPPEVisitor extends PNVisitor {
+ /**
+ * Constructor.
+ *
+ * @param dir
+ * path of this file
+ */
+ public CellPPEVisitor(String dir, CellMapping mapping) {
+ _dir = dir;
+ _mapping = mapping;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param x
+ * process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ // Create a directory for the OS Layer:
+ _ppuDir = _dir + _delimiter + "ppu";
+ File dir = new File(_ppuDir);
+ dir.mkdirs();
+
+ // Copy the header file to this directory
+ // Some library files must be copied to the main directory
+ (new File(_dir + _delimiter + "lib" + _delimiter + "ppu_os.h"))
+ .renameTo(new File(dir.getPath() + _delimiter
+ + "spu_os.h"));
+
+ createOSLayer(x, _mapping.getPPU());
+
+ createMakefilePPU();
+ } catch (Exception e) {
+ System.out.println("CellPPEVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates the OS layer for one SPU
+ *
+ * @param spu
+ * List of all processes a SPU gets
+ * @param index
+ * index of the SPU in the SPU list
+ */
+ protected void createOSLayer(ProcessNetwork x, Vector<Process> ppu) {
+ try {
+ // Create the filename for the new layer
+ String filename = _ppuDir + _delimiter + "ppu_os.cpp";
+
+ // PrintStream for writing to the file
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream _code = new CodePrintStream(file);
+
+ _code = new CodePrintStream(file);
+
+ _code.printPrefixln("#include \"pt.h\"");
+ _code.printPrefixln("#include \"Fifo.h\"");
+ _code.printPrefixln("#include \"WindowedFifo.h\"");
+ _code.printPrefixln("#include \"FastCommunication.h\"");
+ _code.printPrefixln("#include \"common_ppu.h\"");
+ _code.printPrefixln("#include \"common.h\"");
+ for (Process p : ppu) {
+ _code.printPrefixln("#include \".." + _delimiter + "ppu_"
+ + p.getBasename() + _delimiter + p.getBasename()
+ + "Wrapper.h\"");
+ }
+
+ _code.println();
+ _code.printPrefixln("void *ppu( void *ptr )");
+ _code.printLeftBracket();
+
+ // instantiate channels
+ Vector<Channel> channelList = new Vector<Channel>();
+ int indx = 0;
+ for (Channel c : x.getChannelList()) {
+ if (ppu.contains(c.getOrigin())
+ || ppu.contains(c.getTarget())) {
+ channelList.add(c);
+
+ if (c.getType().equals("fifo")) {
+ // This is a IN-Channel --> Add an additional Factor to increase the speed
+ if (ppu.contains(c.getTarget()) && !ppu.contains(c.getOrigin())) {
+ _code.printPrefixln("Fifo " + c.getName()
+ + "(FIFO_SIZE[" + indx +"] * FIFO_SIZE_FACTOR);");
+ // OUT-Channel --> Do not add any factor as we like to stall sometimes
+ } else {
+ _code.printPrefixln("Fifo " + c.getName()
+ + "(FIFO_SIZE[" + indx + "]);");
+ }
+ } else if (c.getType().equals("wfifo")) {
+ _code.printPrefixln("WindowedFifo " + c.getName()
+ + "(FIFO_SIZE[" + indx + "]);");
+ }
+ }
+ indx++;
+ }
+ _code.println();
+
+ // instantiate processes
+ for (Process p : ppu) {
+ _code.printPrefix("int " + p.getName() + "Indices[] = { ");
+ Vector<Integer> iteratorIndex = p.getIteratorIndices();
+ if (iteratorIndex.size() < 4) {
+ while (iteratorIndex.size() < 4) {
+ iteratorIndex.add(-1);
+ }
+ } else if (iteratorIndex.size() > 4) {
+ new RuntimeException("Error: Currently not more than "
+ + "4 iterator dimensions are supported."
+ + "Consider revising " + p.getBasename() + ".");
+ }
+ for (int i = 0; i < 4; i++) {
+ if (i < 3) {
+ _code.print(iteratorIndex.elementAt(i) + ", ");
+ } else {
+ _code.println(iteratorIndex.elementAt(i) + " };");
+ }
+ }
+ _code.println();
+ _code.printPrefixln(p.getBasename() + "Wrapper *" + p.getName() + ";");
+ _code.printPrefixln("try { "
+ + p.getName() + " = new " + p.getBasename()
+ + "Wrapper(\"" + p.getName() + "\", "
+ + p.getName() + "Indices); }");
+ _code.println(" catch(std::bad_alloc &e) {");
+ _code.println(" fprintf(stderr, \"[" + p.getBasename() +"Wrapper] Memory allocation failure\\n\");");
+ _code.println(" exit(1);");
+ _code.println(" }");
+ }
+ _code.println();
+
+ // connect the network
+ for (Process p : ppu) {
+ for (Port port : p.getPortList()) {
+ if (port.getName().equals(port.getBasename())) {
+ _code.printPrefixln(p.getName() + "->_port"
+ + port.getName() + "Fifo = &"
+ + port.getPeerResource().getName() + ";");
+ } else {
+ _code.printPrefix(p.getName() + "->_port"
+ + port.getBasename() + "Fifo");
+ StringTokenizer tokenizer = new StringTokenizer(
+ port.getName().replaceFirst(
+ port.getBasename(), ""), "_");
+ while (tokenizer.hasMoreTokens()) {
+ _code.print("[" + tokenizer.nextToken() + "]");
+ }
+ _code.println(" = &"
+ + port.getPeerResource().getName() + ";");
+ }
+ }
+ }
+ _code.println();
+
+ /**************************************************************************/
+ // This is the synchronisation code
+ _code.println(" for (int i = 0; i < NUM_FIFO; i++)");
+ _code.println(" ((ProcessData *)ptr)->fifoTails[i] = 0;");
+ _code.println(" ");
+
+ int outQueues = 0;
+
+ // Check all out queues on the SPU
+ for (Channel c : x.getChannelList()) {
+
+ // Check all SPUs
+ for (Vector<Process> spu : _mapping.getSPUList()) {
+ if (spu.contains(c.getOrigin()) && !spu.contains(c.getTarget())) {
+ outQueues++;
+ }
+ }
+
+ // Check the PPU
+ if (ppu.contains(c.getOrigin()) && !ppu.contains(c.getTarget())) {
+ outQueues++;
+ }
+ }
+
+ // On how much queues we have to wait
+ _code.println(" uint32_t nrOutQueues = NUM_FIFO;");
+ _code.println(" uint32_t countOutQueues = 0;");
+ _code.println(" uint32_t processNr = 0;");
+ _code.println(" uint32_t message;");
+ _code.println("");
+
+ // Add all out queues of the PPE
+
+ for (Channel c : channelList) {
+ if (ppu.contains(c.getOrigin()) && !ppu.contains(c.getTarget())) {
+ _code.println(" ((ProcessData *)ptr)->fifoTails[" + x.getChannelList().indexOf(c) + "] = (uint64_t) " + c.getName() + ".getQueuePointer();");
+ _code.println(" countOutQueues++;");
+ }
+ }
+
+ // Check to get all messages back
+ _code.println(" ");
+ _code.println(" // Get the offset of the queues");
+ _code.println(" while (countOutQueues < nrOutQueues) {");
+ _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
+ _code.println(" if (!spe_out_mbox_status((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr])) continue;");
+ _code.println(" ");
+ _code.println(" spe_out_mbox_read((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], &message, 1);");
+ _code.println(" ");
+ _code.println(" uint32_t queue = ((message >> 24) & 0xFF);");
+ _code.println(" uint32_t offset = ((message >> 0) & 0xFFFFFF);");
+ _code.println(" ");
+ _code.println(" if (((ProcessData *)ptr)->queueOnSPU[queue] < 0)");
+ _code.println(" ((ProcessData *)ptr)->fifoTails[queue] = offset; // Only the offset if the PPE needs to access the data");
+ _code.println(" else");
+ _code.println(" ((ProcessData *)ptr)->fifoTails[queue] = offset + ((ProcessData *)ptr)->ea_ls_base[processNr];");
+ _code.println(" countOutQueues++;");
+ _code.println(" }");
+ _code.println(" }");
+ _code.println(" ");
+
+ // Send a message that each SPE knows that he can access the list
+ _code.println(" // Send the Okay to all SPEs for that they can start reading the tail pointers of the fifos");
+ _code.println(" message = MSG_OK;");
+ _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
+ _code.println(" spe_in_mbox_write((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);");
+ _code.println(" }");
+
+ /**************************************************************************/
+
+ // initialize processes
+ for (Process p : ppu) {
+ _code.printPrefixln(p.getName() + "->init();");
+ }
+ _code.println();
+
+ // Count the effected channels
+ int countChannels = 0;
+ for (Channel c : channelList) {
+ if (ppu.contains(c.getOrigin())
+ && ppu.contains(c.getTarget())) {
+ continue;
+ } else if (ppu.contains(c.getOrigin()))
+ countChannels++;
+ else if (ppu.contains(c.getTarget()))
+ countChannels++;
+ else
+ System.out.println("ERROR! Channel Mapping is wrong.");
+ }
+
+
+ _code.println(" FastCommunication * com;");
+ _code
+ .println(" try { com = new FastCommunication("
+ + countChannels
+ + ", ((ProcessData *)ptr)->procContentsAll, ((ProcessData *)ptr)->ea_ls_base, ((ProcessData *)ptr)->queueFromSPU, ((ProcessData *)ptr)->queueOnSPU, ((ProcessData *)ptr)->fifoTails); }");
+ _code.println(" catch(std::bad_alloc &e) {");
+ _code.println(" fprintf(stderr, \"[FastCommunication] Memory allocation failure\\n\");");
+ _code.println(" exit(1);");
+ _code.println(" }");
+
+ String channelTyp = "";
+ int i = 0;
+ for (Channel c : channelList) {
+ if (ppu.contains(c.getOrigin())
+ && ppu.contains(c.getTarget())) {
+ // Local channels have no influence on external
+ // communication (should be Windowed Fifos...)
+ channelTyp = "local";
+ continue;
+ } else if (ppu.contains(c.getOrigin())) {
+ channelTyp = "out";
+ } else if (ppu.contains(c.getTarget())) {
+ channelTyp = "in";
+ } else {
+ System.out.println("ERROR! Channel Mapping is wrong.");
+ }
+
+ if (c.getType().equals("fifo")) {
+ _code.println(" com->addFifo(" + (i) + ", &"
+ + c.getName() + ", com->" + channelTyp + ", "
+ + x.getChannelList().indexOf(c) + ");");
+ } else if (c.getType().equals("wfifo")) {
+ _code.println(" com->addWFifo(" + (i) + ", &"
+ + c.getName() + ", com->" + channelTyp + ", "
+ + x.getChannelList().indexOf(c) + ");");
+ }
+ i++;
+ }
+
+ _code.printPrefixln("bool allBlocked = false;");
+ _code.printPrefixln("while(!allBlocked)");
+ _code.printLeftBracket();
+ _code.printPrefixln("allBlocked = true;");
+ for (Process p : ppu) {
+ _code.printPrefixln("if (!" + p.getName()
+ + "->isDetached()) {");
+ _code.printPrefixln(" " + p.getName() + "->fire();");
+ _code.printPrefixln(" allBlocked = false;");
+ _code.printPrefixln("}");
+ _code.printPrefixln("");
+
+
+
+ // Communication only if this process needs some communication
+ for (Channel c : channelList) {
+ // The channel may goes away
+ if (!ppu.contains(c.getOrigin()) || !ppu.contains(c.getTarget())) {
+ if (c.getOrigin().equals(p) || c.getTarget().equals(p)) {
+ _code.printPrefixln("com->update();");
+ _code.printPrefixln("");
+ break;
+ }
+ }
+ }
+
+ }
+ _code.printRightBracket();
+ _code.println();
+
+ _code.println();
+ _code.println(" // Are there any open communication requests?");
+ _code.println(" while (!com->empty())");
+ _code.println(" {");
+ _code.println(" com->update();");
+ _code.println(" }");
+ _code.println(" ");
+ _code.println(" // Send all SPUs the complete message");
+ _code.println(" message = MSG_OK;");
+ _code.println(" for (processNr = 0; processNr < NUM_SPES; processNr++) {");
+ _code.println(" spe_in_mbox_write((spe_context*)((ProcessData *)ptr)->procContentsAll[processNr], (uint32_t*)&message, 1, SPE_MBOX_ANY_NONBLOCKING);");
+ _code.println(" }");
+ _code.println("");
+ for (Process p : ppu) {
+ _code.printPrefixln("delete " + p.getName() + ";");
+ }
+ _code.printPrefixln("delete com;");
+ _code.println();
+ _code.printPrefixln("pthread_exit(NULL);");
+ _code.printRightBracket();
+ } catch (Exception e) {
+ System.out.println("ProtothreadModuleVisitor: "
+ + "exception occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void createMakefilePPU() {
+ try {
+ // Directory of the process
+ String ppuDir = _dir + _delimiter + "ppu";
+
+ // Create the filename for the new wrapper
+ String filename = ppuDir + _delimiter + "Makefile";
+
+ OutputStream file = new FileOutputStream(filename);
+
+ PrintStream _makefilePS = new CodePrintStream(file);
+
+ _makefilePS.println("# Makefile for PPU OS");
+ _makefilePS.println("");
+ _makefilePS.println("src := $(wildcard ../lib/ppu/*.cpp)");
+ _makefilePS.println("obj = $(src:.cpp=.o)");
+ _makefilePS.println("");
+
+ // The Makefile must include all o-Files of the processes needed
+ String dependency = "";
+
+ // Go through all possible processes
+ for (Process p : _mapping.getAllPPUBaseProcess()) {
+ dependency += " .." + _delimiter + "ppu_"
+ + p.getBasename() + _delimiter + p.getBasename()
+ + "Wrapper.o";
+ }
+
+ _makefilePS.println("all: ${obj}");
+ _makefilePS
+ .println("\tppu-g++ -c -I .. -I ../lib -I ../lib/pt -I ../lib/ppu -o ppu_os.o ppu_os.cpp -ftree-vectorize -lm -mtune=cell -O3 -fmodulo-sched -funroll-loops -ffast-math");
+
+ _makefilePS.println();
+ _makefilePS.println("clean: ");
+ _makefilePS.println("\trm ppu_os");
+
+ _makefilePS.println();
+ _makefilePS.println("%.o : ");
+ _makefilePS
+ .println("\tppu-g++ -c -o $(*D)/$(*F).o $(*D)/$(*F).cpp -I .. -I ../lib -I ../lib/pt -I ../lib/ppu -ftree-vectorize -lm -mtune=cell -O3 -fmodulo-sched -funroll-loops -ffast-math");
+ _makefilePS.println();
+
+ } catch (FileNotFoundException e) {
+ System.out.println("CbeProcessVisitor - Makefile: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _ppuDir = null;
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected CellMapping _mapping = null;
+
+}
--- /dev/null
+package dol.visitor.cell;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.SourceCode;
+import dol.visitor.PNVisitor;
+import dol.util.CodePrintStream;
+import dol.util.Copier;
+import dol.util.Sed;
+
+/**
+ * This class is a class for a visitor that is used to generate the main
+ * makefile for the application.
+ *
+ * @author lschor, 2008-10-30
+ *
+ * Remarks: Based on a original file from wolferl for rtems
+ *
+ * Revision: 2008-10-30: Updated the file for the CBE 2008-11-08: Add
+ * double buffering 2009-03-17: Add protothreads
+ */
+public class CellProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir
+ * target directory
+ */
+ public CellProcessVisitor(String dir, HashMap<Port, Integer> portMap,
+ CellMapping mapping) {
+ _dir = dir;
+ _portMap = portMap;
+ _mapping = mapping;
+ }
+
+ /**
+ *
+ * @param x
+ * process network that needs to be processed
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ // Create the Process staff for all processes on the SPU
+ for (Process p : _mapping.getAllSpuBaseProcess()) {
+ createSPEWrapper(p);
+ createMakefileProcess(p);
+ _adaptSources("spu_" + p.getBasename(), p);
+ }
+
+ // Create the Process staff for all processes on the SPU
+ for (Process p : _mapping.getAllPPUBaseProcess()) {
+ createPPEWrapper(p);
+ }
+ } catch (Exception e) {
+ System.out.println("CellProcessVisitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates a Wrapper for an SPE process
+ *
+ * @param p
+ * process that needs to be processed
+ */
+ protected void createSPEWrapper(Process p) {
+ try {
+
+ // Create of each process an own folder
+ // Insert into this folder the source, the wrapper and a makefile
+ String processDir = _dir + _delimiter + "spu_"
+ + p.getBasename();
+ File dir = new File(processDir);
+ dir.mkdirs();
+
+ /***************** class File ******************************/
+
+ // Create the filename for the new wrapper
+ String filename = processDir + _delimiter + p.getBasename()
+ + "Wrapper.cpp";
+ File process_file = new File(filename);
+ File pattern_file = new File(_dir + _delimiter + _tempDirName
+ + _delimiter + "spu_process_wrapper_template.cpp");
+ new Copier().copyFile(pattern_file, process_file);
+
+ String includes = "";
+ for (SourceCode code : p.getSrcList()) {
+ includes += "#include \"" + code.getLocality() + "\""
+ + System.getProperty("line.separator");
+ }
+
+ Sed sed = new Sed();
+ // Replace the include of the main c-file
+ sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes);
+ // Replace the process-name in the whole file
+ sed.sed(filename, "@PROCESSNAME@", p.getBasename());
+ sed.sed(filename, "@PROCESSNAME_UPPER@", p.getBasename()
+ .substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1));
+
+ /***************** header File ******************************/
+ // Create the filename for the new wrapper
+ filename = processDir + _delimiter + p.getBasename()
+ + "Wrapper.h";
+ process_file = new File(filename);
+ pattern_file = new File(_dir + _delimiter + _tempDirName
+ + _delimiter + "spu_process_wrapper_template.h");
+ new Copier().copyFile(pattern_file, process_file);
+
+ includes = "";
+ for (SourceCode code : p.getSrcList()) {
+ includes += "#include \"" + code.getLocality() + "\""
+ + System.getProperty("line.separator");
+ }
+
+ sed = new Sed();
+ // Replace the include of the main c-file
+ sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes);
+ // Replace the process-name in the whole file
+ sed.sed(filename, "@PROCESSNAME@", p.getBasename());
+
+ // Create the correct Port and Fifo List
+ String fifolist = "";
+ Vector<String> basenames = new Vector<String>();
+ for (Port port : p.getPortList()) {
+ if (!basenames.contains(port.getBasename())) {
+ basenames.add(port.getBasename());
+ } else {
+ continue;
+ }
+
+ Channel c = (Channel) port.getPeerResource();
+ if (port.getName().equals(port.getBasename())) {
+ if (c.getType().equals("fifo")) {
+ fifolist += "Fifo* _port" + port.getName()
+ + "Fifo;";
+ } else if (c.getType().equals("wfifo")) {
+ fifolist += "WindowedFifo* _port" + port.getName()
+ + "Fifo;";
+ }
+ } else {
+ if (c.getType().equals("fifo")) {
+ fifolist += "Fifo* _port" + port.getBasename()
+ + "Fifo";
+ } else if (c.getType().equals("wfifo")) {
+ fifolist += "WindowedFifo* _port"
+ + port.getBasename() + "Fifo";
+ }
+ StringTokenizer tokenizer = new StringTokenizer(port
+ .getRange(), ";");
+ while (tokenizer.hasMoreTokens()) {
+ fifolist += "[" + tokenizer.nextToken() + "]";
+ }
+ fifolist += ";";
+ }
+ }
+
+ // Set the correct Fifo's
+ sed.sed(filename, "@FIFO@", fifolist);
+
+ /***************** source File ******************************/
+
+ // Go through all source files
+ for (SourceCode sourceCode : p.getSrcList()) {
+ // Copy the files to the new folder
+ String oldFilename = _dir
+ + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+ filename = processDir
+ + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ if (new File(filename).exists()) {
+ new File(filename).delete();
+ }
+
+ new File(oldFilename).renameTo(new File(filename));
+
+ // Copy also the c-files
+ if ((oldFilename.substring(oldFilename.length() - 2))
+ .equals(".h")) {
+ String newFileNameC = filename.substring(0, filename
+ .length() - 2)
+ + ".c";
+ if (new File(newFileNameC).exists()) {
+ new File(newFileNameC).delete();
+ }
+ // new Copier().copyFile(new File(oldFilename.substring(0,
+ // oldFilename.length() - 2) + ".c"), new
+ // File(filename.substring(0, filename.length() - 2) +
+ // ".c"));
+ new File(oldFilename.substring(0,
+ oldFilename.length() - 2)
+ + ".c").renameTo(new File(newFileNameC));
+ }
+
+ // Update the files for the DOL project
+ sed.sed(filename, "<dol.h>", "\"dol.h\"");
+
+ }
+ } catch (Exception e) {
+ System.out.println("CbeProcessVisitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates a Wrapper for a PPE process
+ *
+ * @param p
+ * process that needs to be processed
+ */
+ protected void createPPEWrapper(Process p) {
+ try {
+ // Create of each process an own folder
+ // Insert into this folder the source, the wrapper and a makefile
+ String processDir = _dir + _delimiter + "ppu_"
+ + p.getBasename();
+ File dir = new File(processDir);
+ dir.mkdirs();
+
+ // Go through all source files
+ for (SourceCode sourceCode : p.getSrcList()) {
+ // Copy the files to the new folder
+ String oldFilename = _dir
+ + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+ String filename = processDir
+ + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ if (new File(filename).exists()) {
+ new File(filename).delete();
+ }
+
+ new File(oldFilename).renameTo(new File(filename));
+
+ // Copy also the c-files
+ if ((oldFilename.substring(oldFilename.length() - 2))
+ .equals(".h")) {
+ String newFileNameC = filename.substring(0, filename
+ .length() - 2)
+ + ".c";
+ if (new File(newFileNameC).exists()) {
+ new File(newFileNameC).delete();
+ }
+ new File(oldFilename.substring(0,
+ oldFilename.length() - 2)
+ + ".c").renameTo(new File(newFileNameC));
+ }
+ }
+
+ _createPPECppFile(dir, p);
+ _createPPEHeaderFile(dir, p);
+ _adaptSources("ppu_" + p.getBasename(), p);
+ createMakeFilePPUProcess("ppu_" + p.getBasename(), p);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ private void _createPPECppFile(File dir, Process p) throws IOException {
+ String classname = p.getBasename() + "Wrapper";
+ String filename = dir + _delimiter + classname + ".cpp";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ ps.printPrefixln("#include \"" + classname + ".h\"");
+ ps.printPrefixln("#include \"dolSupport.h\"");
+ ps.printPrefixln("#include <string.h>");
+ ps.println();
+ for (SourceCode sr : p.getSrcList()) {
+ ps.printPrefixln("#include \"" + sr.getLocality() + "\"");
+ }
+ ps.println();
+ ps.printPrefixln(classname + "::" + classname
+ + "(char* name, int iteratorIndex[4]) :");
+ ps.printPrefixln(" ProcessWrapper(name, iteratorIndex)");
+ ps.printLeftBracket();
+ ps.printPrefixln("_state = (LocalState)new "
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State;");
+ ps.printPrefixln("_process.init = " + p.getBasename() + "_init;");
+ ps.printPrefixln("_process.fire = " + p.getBasename() + "_fire;");
+ ps.printPrefixln("_process.local = _state;");
+ ps.printPrefixln("_process.wptr = (void*)&_wrapper_data;");
+ ps.printPrefixln("_wrapper_data.wrapper = this;");
+ ps.printRightBracket();
+ ps.println();
+ ps.printPrefixln(classname + "::~" + classname + "()");
+ ps.printLeftBracket();
+ ps.printPrefixln("if (_state)");
+ ps.printPrefixln(" delete ("
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State*)_state;");
+ // ps.printPrefixln(" delete _state;");
+ ps.printRightBracket();
+ }
+
+ /**
+ *
+ */
+ private void _createPPEHeaderFile(File dir, Process p)
+ throws IOException {
+ String classname = p.getBasename() + "Wrapper";
+ String filename = dir + _delimiter + classname + ".h";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ ps.printPrefixln("#ifndef " + classname.toUpperCase() + "_H");
+ ps.printPrefixln("#define " + classname.toUpperCase() + "_H");
+ ps.println();
+ ps.printPrefixln("#include \"ProcessWrapper.h\"");
+ ps.printPrefixln("#include \"Fifo.h\"");
+ ps.printPrefixln("#include \"WindowedFifo.h\"");
+ ps.println();
+ ps.printPrefixln("class " + classname + ";");
+ ps.println();
+ ps.printPrefixln("typedef struct _" + p.getBasename() + "_data {");
+ ps.printPrefixln(" int lc;");
+ ps.printPrefixln(" " + classname + " *wrapper;");
+ ps.printPrefixln("} " + p.getBasename() + "_data;");
+ ps.println();
+ ps
+ .printPrefixln("class " + classname
+ + " : public ProcessWrapper");
+ ps.printLeftBracket();
+ ps.printPrefixln("public:");
+ ps.printPrefixln(" " + classname + "(char* name, "
+ + "int iteratorIndex[4]);");
+ ps.printPrefixln(" virtual ~" + classname + "();");
+ ps.println();
+
+ Vector<String> basenames = new Vector<String>();
+ for (Port port : p.getPortList()) {
+ if (!basenames.contains(port.getBasename())) {
+ basenames.add(port.getBasename());
+ } else {
+ continue;
+ }
+
+ Channel c = (Channel) port.getPeerResource();
+ if (port.getName().equals(port.getBasename())) {
+ if (c.getType().equals("fifo")) {
+ ps.printPrefixln(" Fifo* _port" + port.getName()
+ + "Fifo;");
+ } else if (c.getType().equals("wfifo")) {
+ ps.printPrefixln(" WindowedFifo* _port"
+ + port.getName() + "Fifo;");
+ }
+ } else {
+ if (c.getType().equals("fifo")) {
+ ps.printPrefix(" Fifo* _port" + port.getBasename()
+ + "Fifo");
+ } else if (c.getType().equals("wfifo")) {
+ ps.printPrefix(" WindowedFifo* _port"
+ + port.getBasename() + "Fifo");
+ }
+ StringTokenizer tokenizer = new StringTokenizer(port
+ .getRange(), ";");
+ while (tokenizer.hasMoreTokens()) {
+ ps.print("[" + tokenizer.nextToken() + "]");
+ }
+ ps.println(";");
+ }
+ }
+ ps.println("");
+ ps.printPrefixln("protected:");
+ ps.printPrefixln(" struct _local_states *_state;");
+ ps
+ .printPrefixln(" " + p.getBasename()
+ + "_data _wrapper_data;");
+ ps.printRightBracket();
+
+ ps.printPrefixln(";");
+ ps.println();
+ ps.printPrefixln("#endif");
+ }
+
+ /**
+ * Create the makefile for a special process --> Each subprocess gets its
+ * own makefile
+ *
+ * @param p
+ * process for which the makefile should be created
+ */
+ protected void createMakefileProcess(Process p) {
+ try {
+ // Directory of the process
+ String processDir = _dir + _delimiter + "spu_"
+ + p.getBasename();
+
+ // Create the filename for the new wrapper
+ String filename = processDir + _delimiter + "Makefile";
+ // File makefile = new File(filename);
+
+ OutputStream file;
+
+ file = new FileOutputStream(filename);
+
+ PrintStream _makefilePS = new CodePrintStream(file);
+
+ _makefilePS.println("# Makefile for process "
+ + p.getBasename());
+ _makefilePS.println("");
+
+ String dependency = "all: " + p.getBasename() + "Wrapper.cpp";
+
+ for (SourceCode code : p.getSrcList()) {
+ dependency += " " + code.getLocality();
+ }
+
+ _makefilePS.println(dependency);
+ _makefilePS
+ .println("\tspu-g++ -c -I .. -I ../lib -o "
+ + p.getBasename()
+ + "Wrapper.o "
+ + p.getBasename()
+ + "Wrapper.cpp -ftree-vectorize -mtune=cell -O3 -fmodulo-sched -funroll-loops -ffast-math -fno-rtti -ffunction-sections -fdata-sections" );
+ _makefilePS.println("clean: ");
+ _makefilePS.println("\trm " + p.getBasename() + "Wrapper.o");
+ _makefilePS.println();
+
+ } catch (FileNotFoundException e) {
+ System.out.println("CbeProcessVisitor - Makefile: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ private void createMakeFilePPUProcess(String subdir, Process p) {
+ try {
+ // Directory of the process
+ String processDir = _dir + _delimiter + subdir;
+
+ // Create the filename for the new wrapper
+ String filename = processDir + _delimiter + "Makefile";
+ // File makefile = new File(filename);
+
+ OutputStream file;
+
+ file = new FileOutputStream(filename);
+
+ PrintStream _makefilePS = new CodePrintStream(file);
+
+ _makefilePS.println("# Makefile for process "
+ + p.getBasename());
+ _makefilePS.println("");
+
+ String dependency = "all: " + p.getBasename() + "Wrapper.cpp";
+
+ for (SourceCode code : p.getSrcList()) {
+ dependency += " " + code.getLocality();
+ }
+ _makefilePS.println("# General definitions:");
+ _makefilePS.println("CC = ppu-g++");
+ _makefilePS
+ .println("CCFLAGS = -ftree-vectorize -O3 -maltivec -funroll-loops -mabi=altivec -mcpu=cell");
+ _makefilePS.println("COMPILE = $(CC) $(CCFLAGS) -c");
+
+ _makefilePS.println(dependency);
+ _makefilePS
+ .println("\t$(COMPILE) -o "
+ + p.getBasename()
+ + "Wrapper.o "
+ + p.getBasename()
+ + "Wrapper.cpp -I .. -I ../lib -I ../lib/ppu -I ../lib/pt;");
+ _makefilePS.println("clean: ");
+ _makefilePS.println("\trm " + p.getBasename() + "Wrapper.o");
+ _makefilePS.println();
+
+ } catch (FileNotFoundException e) {
+ System.out
+ .println("CbeProcessVisitor - Makefile PPU: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Make modifications to source files of a process. Port names need to be
+ * strings for the SystemC code generation. Therefore, in the header files
+ * integer port names are put into quotation marks.
+ *
+ * @param p
+ * process whose sources should be adapted
+ * @throws IOException
+ * @author haidw
+ */
+ protected void _adaptSources(String subdir, Process p)
+ throws IOException {
+ Sed sed = new Sed();
+ // modify header file
+ for (Port port : p.getPortList()) {
+ String processHeaderFile;
+
+ for (SourceCode sr : p.getSrcList()) {
+ processHeaderFile = _dir
+ + _delimiter
+ + subdir
+ + _delimiter
+ + sr.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ sed.sed(processHeaderFile, "(#define[ ]*PORT_\\w*[ ]*)\"?"
+ + port.getBasename() + "\"?", "$1 "
+ + "static_cast<" + p.getBasename()
+ + "Wrapper *>((static_cast<" + p.getBasename()
+ + "_data *>(p->wptr))->wrapper)->_port"
+ + port.getBasename() + "Fifo");
+ }
+ }
+
+ // modify source file
+ for (SourceCode sr : p.getSrcList()) {
+ String processSourceFile = _dir + _delimiter + subdir
+ + _delimiter + sr.getLocality();
+
+ String line;
+ StringBuffer buffer = new StringBuffer();
+ FileInputStream fileInputStream = new FileInputStream(
+ processSourceFile);
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(fileInputStream));
+ while ((line = reader.readLine()) != null) {
+ buffer.append(line + "\n");
+ }
+ reader.close();
+
+ String file = buffer.toString();
+ // insert PT_BEGIN() at beginning of fire() function
+ file = file.replaceAll("(int[ ]*" + p.getBasename()
+ + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)"
+ + "[\\s\\S&&[^\\{]]*)\\{", "$1"
+ + System.getProperty("line.separator") + "{"
+ + System.getProperty("line.separator")
+ + " PT_BEGIN((pt*)(p->wptr));");
+
+ // replace last return statement in fire function by PT_END()
+ // find beginning of fire function
+ Matcher matcher = Pattern.compile(
+ "(int[ ]*" + p.getBasename()
+ + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)"
+ + "[\\s\\S&&[^\\{]]*)\\{").matcher(file);
+ matcher.find();
+ int i = 0;
+ try {
+ i = matcher.start();
+ } catch (Exception e) {
+ System.out.println("Error: could not find "
+ + p.getBasename() + "_fire() function in "
+ + processSourceFile + ".");
+ e.printStackTrace();
+ }
+ int openBraces = 0; // counter for open curly braces
+ // position of last return statement
+ int lastReturnStartPosition = 0;
+ int lastReturnEndPosition = 0;
+ while (i < file.length()) {
+ // ignore single-line comments
+ if (i < (file.length() - 1)
+ && file.substring(i, i + 2).equals("//")) {
+ while (!file.substring(i, i + 1).equals("\n")) {
+ i++;
+ }
+ }
+ // ignore multi-line comments
+ else if (i < (file.length() - 1)
+ && file.substring(i, i + 2).equals("/*")) {
+ while (!file.substring(i, i + 2).equals("*/")) {
+ i++;
+ }
+ }
+ // ignore strings
+ else if (file.substring(i, i + 1).equals("\"")) {
+ matcher = Pattern.compile("[\\s\\S&&[^\\\\]]\\\"")
+ .matcher(file);
+ matcher.find(i + 1);
+ i = matcher.start() + 1;
+ } else if (i < (file.length() - 5)
+ && file.substring(i, i + 6).equals("return")) {
+ lastReturnStartPosition = i;
+ while (!file.substring(i, i + 1).equals(";")) {
+ i++;
+ }
+ lastReturnEndPosition = i;
+ } else if (file.substring(i, i + 1).equals("{")) {
+ openBraces++;
+ } else if (file.substring(i, i + 1).equals("}")) {
+ openBraces--;
+ if (openBraces == 0) {
+ break;
+ }
+ }
+ i++;
+ }
+
+ file = file.substring(0, lastReturnStartPosition)
+ + "/* "
+ + file.substring(lastReturnStartPosition,
+ lastReturnEndPosition + 1)
+ + " (commented out by DOL) */"
+ + System.getProperty("line.separator")
+ + " PT_END((pt*)(p->wptr));"
+ + System.getProperty("line.separator")
+ + file.substring(lastReturnEndPosition + 2, file
+ .length());
+
+ BufferedWriter out = new BufferedWriter(new FileWriter(
+ processSourceFile));
+ out.write(file);
+ out.close();
+ }
+ }
+
+ protected CellMapping _mapping;
+ protected String _dir = null;
+ protected HashMap<Port, Integer> _portMap;
+
+ protected static String _libDirName = "lib";
+ protected static String _tempDirName = "template";
+
+}
--- /dev/null
+package dol.visitor.cell;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+import dol.util.CodePrintStream;
+
+/**
+ * This class is a class for a visitor that is used to generate the the OS for
+ * the SPEs.
+ *
+ * @author lschor, 2009-03-24 * Revision: 2009-03-24: Created
+ */
+public class CellSPEVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir
+ * path of this file
+ */
+ public CellSPEVisitor(String dir, CellMapping mapping) {
+ _dir = dir;
+ _mapping = mapping;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param x
+ * process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ // Create a directory where all SPU's are stored:
+ _spuDir = _dir + _delimiter + "spu";
+ File dir = new File(_spuDir);
+ dir.mkdirs();
+
+ // Copy the header file to this directory
+ // Some library files must be copied to the main directory
+ (new File(_dir + _delimiter + "lib" + _delimiter + "spu_os.h"))
+ .renameTo(new File(dir.getPath() + _delimiter
+ + "spu_os.h"));
+
+ ArrayList<Vector<Process>> spuList = _mapping.getSPUList();
+
+ int i = 0;
+ for (Vector<Process> spu : spuList) {
+ createOSLayer(x, spu, i++);
+ }
+
+ createMakefileSPU();
+
+ } catch (Exception e) {
+ System.out.println("CellSPEVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Create the makefile for a SPU (so for the layer). Each SPU gets its own
+ * Makefile
+ *
+ * @param spu
+ * SPU for which the Makefile should be used
+ */
+ protected void createMakefileSPU() {
+ try {
+ // Directory of the process
+ String spuDir = _dir + _delimiter + "spu";
+
+ // Create the filename for the new wrapper
+ String filename = spuDir + _delimiter + "Makefile";
+
+ OutputStream file = new FileOutputStream(filename);
+
+ PrintStream _makefilePS = new CodePrintStream(file);
+
+ _makefilePS.println("# Makefile for SPU OS");
+ _makefilePS.println("");
+ _makefilePS.println("src := $(wildcard ../lib/spu/*.cpp)");
+ _makefilePS.println("obj = $(src:.cpp=.o)");
+ _makefilePS.println("");
+
+ // The Makefile must include all o-Files of the processes needed
+ String dependency = "";
+
+ // Go through all possible processes
+ for (Process p : _mapping.getAllSpuBaseProcess()) {
+ dependency += " .." + _delimiter + "spu_"
+ + p.getBasename() + _delimiter + p.getBasename()
+ + "Wrapper.o";
+ }
+
+ _makefilePS.println("all: ${obj}" + dependency);
+ for (int i = 0; i < _mapping.getNrSPE(); i++) {
+ _makefilePS.println("\tspu-g++ -Wall -I .. -I ../lib -o "
+ + "spu_os_" + i + " spu_os_" + i + ".cpp "
+ + "../lib/spu/Fifo.o ../lib/spu/WindowedFifo.o "
+ + "../lib/spu/dolSupport.o "
+ + "../lib/spu/proc_wrapper.o ../lib/spu/common.o "
+ + "../lib/spu/FastCommunication.o" + dependency
+ + " -ftree-vectorize -lm -mtune=cell -O3"
+ + " -fmodulo-sched -funroll-loops "
+ + " -ffast-math -fno-rtti -ffunction-sections"
+ + " -fdata-sections -Wl,--gc-sections");
+ }
+ _makefilePS.println();
+ _makefilePS.println("clean: ");
+ for (int i = 0; i < _mapping.getNrSPE(); i++) {
+ _makefilePS.println("\trm spu_os_" + i);
+ }
+ _makefilePS.println();
+ _makefilePS.println("%.o : ");
+ _makefilePS.println("\tspu-g++ -c -o $(*D)/$(*F).o "
+ + "$(*D)/$(*F).cpp -I .. -I"
+ + " ../lib -ftree-vectorize -mtune=cell -O3"
+ + " -fmodulo-sched -funroll-loops -ffast-math"
+ + " -fno-rtti -ffunction-sections -fdata-sections");
+ _makefilePS.println();
+ } catch (FileNotFoundException e) {
+ System.out.println("CbeProcessVisitor - Makefile: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates the OS layer for one SPU
+ *
+ * @param spu
+ * List of all processes a SPU gets
+ * @param index
+ * index of the SPU in the SPU list
+ */
+ protected void createOSLayer(ProcessNetwork x, Vector<Process> spu,
+ int index) {
+ try {
+ // Create the filename for the new layer
+ String filename = _spuDir + _delimiter + "spu_os_" + index
+ + ".cpp";
+
+ // PrintStream for writing to the file
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream _code = new CodePrintStream(file);
+
+ _code.println("/****************************************************************");
+ _code.println(" * SPU OS file");
+ _code.println(" * Description: OS for one SPU");
+ _code.println(" */");
+ _code.println();
+ _code.println("#include \"spu_os.h\"");
+
+ // Must include all possible wrappers
+ Vector<String> pList = new Vector<String>();
+ // Go through all possible processes
+ for (Process p : spu) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ pList.add(basename);
+ _code.println("#include \".." + _delimiter + "spu_"
+ + p.getBasename() + _delimiter
+ + p.getBasename() + "Wrapper.h\"");
+ }
+ }
+
+ _code.println("");
+ _code.println("// Main application");
+ _code.println("int main(int speid , uint64_t argp)");
+ _code.println("{");
+ _code.println(" // reserve DMA tag ID");
+ _code.println(" uint32_t tag_id;");
+ _code.println(" if((tag_id=mfc_tag_reserve())==MFC_TAG_INVALID){");
+ _code.println(" printf(\"SPE: ERROR - can't reserve a tag ID\"); return 1;");
+ _code.println(" }");
+ _code.println(" ");
+ _code.println(" // Get the context information for the whole system");
+ _code.println(" mfc_get((void*) &ctx_spu, argp, sizeof(ctx_spu), tag_id, 0, 0);");
+ _code.println(" mfc_write_tag_mask(1<<tag_id);");
+ _code.println(" mfc_read_tag_status_all();");
+ _code.println(" ");
+ _code.println(" // This is the number of processes of this SPE");
+ _code.println(" uint64_t nr_proc = ctx_spu.procContentsLen;");
+ _code.println(" ");
+ _code.println(" // Get the addresses of the contexts for the Processes");
+ _code.println(" uint64_t context_addr[nr_proc];");
+ _code.println(" mfc_get((void*)context_addr, ctx_spu.procContents, sizeof(uint64_t) * roundDMA(nr_proc), tag_id,0,0);");
+ _code.println(" ");
+ _code.println(" mfc_write_tag_mask(1<<tag_id);");
+ _code.println(" mfc_read_tag_status_all();");
+ _code.println(" ");
+ _code.println(" int32_t queueFromSPU[roundDMA(NUM_FIFO)] __attribute__ ((aligned(16)));");
+ _code.println(" int32_t queueOnSPU[roundDMA(NUM_FIFO)] __attribute__ ((aligned(16)));");
+ _code.println(" uint64_t tailAddresses[roundDMA(NUM_FIFO)] __attribute__ ((aligned(16)));");
+ _code.println(" ");
+ _code.println(" mfc_get((void*)queueFromSPU, ctx_spu.queueFromSPU, sizeof(int32_t) * roundDMA(NUM_FIFO), tag_id,0,0);");
+ _code.println(" mfc_write_tag_mask(1<<tag_id);");
+ _code.println(" mfc_read_tag_status_all();");
+ _code.println(" ");
+ _code.println(" mfc_get((void*)queueOnSPU, ctx_spu.queueOnSPU, sizeof(int32_t) * roundDMA(NUM_FIFO), tag_id,0,0);");
+ _code.println(" mfc_write_tag_mask(1<<tag_id);");
+ _code.println(" mfc_read_tag_status_all();");
+ _code.println("");
+ _code.println(" // Get the base addresses");
+ _code.println(" uint64_t procContentsAll[roundDMA(NUM_SPES)] __attribute__ ((aligned(16)));");
+ _code.println(" ");
+ _code.println(" mfc_get((void*)procContentsAll, ctx_spu.procContentsAll, sizeof(uint64_t) * roundDMA(NUM_SPES), tag_id,0,0);");
+ _code.println(" mfc_write_tag_mask(1<<tag_id);");
+ _code.println(" mfc_read_tag_status_all();");
+ _code.println(" ");
+ _code.println(" // Read the base address");
+ _code.println(" uint64_t ea_base = ctx_spu.ea_base;");
+ _code.println(" ");
+
+ Vector<Channel> channelList = new Vector<Channel>();
+ int indx = 0;
+ // instantiate channels
+ for (Channel c : x.getChannelList()) {
+ if (spu.contains(c.getOrigin())
+ || spu.contains(c.getTarget())) {
+ channelList.add(c);
+ if (c.getType().equals("fifo")) {
+ _code.printPrefixln(" Fifo " + c.getName() + "("
+ + "FIFO_SIZE[" + indx + "]);");
+ } else if (c.getType().equals("wfifo")) {
+ _code.printPrefixln(" WindowedFifo "
+ + c.getName() + "(" + "FIFO_SIZE[" + indx
+ + "]);");
+ }
+ }
+ indx++;
+ }
+
+ _code.println();
+
+ // Go through all processes
+ for (Process p : spu) {
+ // Create the process wrapper
+ _code.println(" " + p.getBasename() + "Wrapper *" + p.getName() +";");
+ _code.println(" try { "
+ + p.getName() + " = new " + p.getBasename()
+ + "Wrapper (context_addr[" + spu.indexOf(p)
+ + "]); }");
+ _code.println(" catch(std::bad_alloc &e) {");
+ _code.println(" fprintf(stderr, \"[" + p.getBasename() +"Wrapper] Memory allocation failure\\n\");");
+ _code.println(" exit(1);");
+ _code.println(" }");
+
+ // Create the port-mapping
+ for (Port port : p.getPortList()) {
+ if (port.getName().equals(port.getBasename())) {
+ _code.printPrefixln(" " + p.getName() + "->_port"
+ + port.getName() + "Fifo = &"
+ + port.getPeerResource().getName() + ";");
+ } else {
+ _code.printPrefix(" " + p.getName() + "->_port"
+ + port.getBasename() + "Fifo");
+ StringTokenizer tokenizer = new StringTokenizer(
+ port.getName().replaceFirst(
+ port.getBasename(), ""), "_");
+ while (tokenizer.hasMoreTokens()) {
+ _code.print("[" + tokenizer.nextToken() + "]");
+ }
+ _code.println(" = &"
+ + port.getPeerResource().getName() + ";");
+ }
+ }
+ _code.println();
+ }
+
+ // Count the effected channels
+ int countChannels = 0;
+ for (Channel c : channelList) {
+ if (spu.contains(c.getOrigin())
+ && spu.contains(c.getTarget())) {
+ continue;
+ } else if (spu.contains(c.getOrigin()))
+ countChannels++;
+ else if (spu.contains(c.getTarget()))
+ countChannels++;
+ else
+ System.out.println("ERROR! Channel Mapping is wrong.");
+ }
+
+ _code.println(" // inited all queues, now one has to know:");
+ _code.println(" // sends out the start addresses to the SPU (of all out channels)");
+
+ // Check all out queues on the SPU
+ _code.println(" uint32_t queuemessage;");
+ for (Channel c : channelList) {
+ if (spu.contains(c.getOrigin()) && !spu.contains(c.getTarget())) {
+ _code.println(" queuemessage = CREATEQUEUEMESSAGE(" + x.getChannelList().indexOf(c) + ", (uint32_t)" + c.getName() + ".getQueuePointer());");
+ _code.println(" spu_write_out_mbox(queuemessage);");
+ }
+ }
+
+ _code.println(" ");
+ _code.println(" // Wait until we get the okey to read the tail pointers");
+ _code.println(" uint32_t messageIn = spu_read_in_mbox();");
+ _code.println("");
+ _code.println(" mfc_get((void*)tailAddresses, ctx_spu.fifoTails, sizeof(uint64_t) * roundDMA(NUM_FIFO), tag_id,0,0);");
+ _code.println(" mfc_write_tag_mask(1<<tag_id);");
+ _code.println(" mfc_read_tag_status_all();");
+ _code.println(" FastCommunication * com;");
+ _code.println(" try { com = new FastCommunication("
+ + countChannels + ", ea_base, procContentsAll, queueFromSPU, queueOnSPU, tailAddresses); }");
+ _code.println(" catch(std::bad_alloc &e) {");
+ _code.println(" fprintf(stderr, \"[FastCommunication] Memory allocation failure\\n\");");
+ _code.println(" exit(1);");
+ _code.println(" }");
+
+ String channelTyp = "";
+ int i = 0;
+ for (Channel c : channelList) {
+ if (spu.contains(c.getOrigin())
+ && spu.contains(c.getTarget())) {
+ // Local channels have no influence on external
+ // communication (should be Windowed Fifos...)
+ channelTyp = "local";
+ continue;
+ } else if (spu.contains(c.getOrigin()))
+ channelTyp = "out";
+ else if (spu.contains(c.getTarget()))
+ channelTyp = "in";
+ else
+ System.out.println("ERROR! Channel Mapping is wrong.");
+
+ if (c.getType().equals("fifo")) {
+ _code.println(" com->addFifo(" + (i) + ", &"
+ + c.getName() + ", com->" + channelTyp + ", "
+ + x.getChannelList().indexOf(c) + ");");
+ }
+ else if (c.getType().equals("wfifo")) {
+ _code.println(" com->addWFifo(" + (i) + ", &"
+ + c.getName() + ", com->" + channelTyp + ", "
+ + x.getChannelList().indexOf(c) + ");");
+ }
+ i++;
+ }
+
+ // The scheduler (yes, this could be optimized...)
+ _code.println("");
+ _code.println(" printf(\"SPU " + index + ": start to execute\\n\"); ");
+ _code.println("");
+ _code.println(" bool allBlocked = false;");
+ _code.println(" while (!allBlocked)");
+ _code.println(" {");
+ _code.println(" allBlocked = true;");
+ for (Process p : spu) {
+ _code.println(" if (!" + p.getName()
+ + "->isDetached())");
+ _code.println(" {");
+ _code.println(" " + p.getName() + "->fire();");
+ _code.println(" allBlocked = false;");
+ _code.println(" }");
+
+ // communication only if this process needs some communication
+ for (Channel c : channelList) {
+ // the channel may go away
+ if (!spu.contains(c.getOrigin()) || !spu.contains(c.getTarget())) {
+ if (c.getOrigin().equals(p) || c.getTarget().equals(p)) {
+ _code.println(" com->update();");
+ break;
+ }
+ }
+ }
+ _code.println();
+ }
+ _code.println(" }");
+ _code.println();
+
+ // End --> wait until all communications are finished
+ _code
+ .println(" // Are there any open communication requests?");
+ _code.println(" while (!com->empty())");
+ _code.println(" {");
+ _code.println(" com->update();");
+ _code.println(" }");
+
+ for (Process p : spu) {
+ _code.println(" delete " + p.getName() + ";");
+ }
+
+ _code.println(" delete com;");
+ _code.println(" ");
+ _code.println(" // release tag ID before exiting");
+ _code.println(" mfc_tag_release(tag_id);");
+ _code.println(" ");
+ _code.println(" uint32_t message = CREATEFASTMESSAGE(SPE_COMPLETE, 0, 0);");
+ _code.println(" spu_write_out_mbox(message);");
+ _code.println(" ");
+ _code.println(" messageIn = spu_read_in_mbox();");
+ _code.println("}");
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected String _spuDir = null;
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected CellMapping _mapping = null;
+}
--- /dev/null
+package dol.visitor.cell;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Vector;
+
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.main.UserInterface;
+import dol.visitor.PNVisitor;
+import dol.util.Copier;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a CELL package.
+ */
+public class CellVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param packageName name of the Cell directory
+ */
+ public CellVisitor(String packageName) {
+ _packageName = packageName;
+ _ui = UserInterface.getInstance();
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param pn process network that needs to be rendered.
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ // Create the library
+ File lib = new File(_packageName + _delimiter + "lib");
+ lib.mkdirs();
+
+ //copy library files
+ File source = new File(_ui.getMySystemCLib().
+ replaceAll("systemC", "cell").replace("%20", " "));
+ new Copier().copy(source, lib);
+
+ // Create the template
+ File template = new File(_packageName + _delimiter + "template");
+ template.mkdirs();
+
+ //copy the templates
+ source = new File(_ui.getMySystemCLib().replaceAll("systemC", "cell").replace("lib", "template").replace("%20", " "));
+ new Copier().copy(source, template);
+
+ // Some library files must be copied to the main directory
+ (new File(lib.getPath() + _delimiter + "ppu_main.h")).renameTo(new File (dir.getPath() + _delimiter + "ppu_main.h"));
+
+ //copy process source code
+ source = new File(_srcDirName.replace("%20", " "));
+ new Copier().copy(source, dir);
+
+ createPortMap(pn);
+
+ // Create the mapping for this process network on the cell
+ CellMapping mapping = new CellMapping(pn, "predefined", true, MAX_SPUS);
+
+ pn.accept(new CellMakefileVisitor(_packageName, mapping));
+ pn.accept(new CellProcessVisitor(_packageName, _portMap, mapping));
+ pn.accept(new CellModuleVisitor(_packageName, _portMap, mapping));
+ pn.accept(new CellConstantVisitor(_packageName, mapping));
+ pn.accept(new CellSPEVisitor(_packageName, mapping));
+ pn.accept(new CellPPEVisitor(_packageName, mapping));
+ }
+ catch (Exception e) {
+ System.out.println("CellVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Create a hashmap which maps each port of the given process network
+ * to an integer. For each process, ports are numbered with integers
+ * starting from 0.
+ *
+ * @param pn process network for which the map should be generated
+ */
+ protected void createPortMap(ProcessNetwork pn) {
+ _portMap = new HashMap<Port, Integer>();
+
+ for (Process process : pn.getProcessList()) {
+ int portCount = 0;
+ Vector<Port> portList = process.getPortList();
+ Vector<String> portNameList = new Vector<String>();
+ portNameList.clear();
+ HashMap<String, Integer> portMap =
+ new HashMap<String, Integer>();
+ portMap.clear();
+
+ for (int i = 0; i < portList.size(); i++) {
+ //treat single ports differently than iterated ports
+ String portName = portList.elementAt(i).getName();
+ String baseName = portList.elementAt(i).getBasename();
+
+ if (portName.equals(baseName)) {
+ portNameList.add(portName);
+ portMap.put(portName, portCount++);
+ } else {
+ String range_indices = portList.elementAt(i).getRange();
+ Vector<Integer> range_indices_values = getIndex(range_indices, ";");
+
+ String port_indices = portName;
+ port_indices.replaceAll(baseName, "");
+ Vector<Integer> port_indices_values = getIndex(port_indices, "_");
+
+ if (!portNameList.contains(baseName)) {
+ portNameList.add(baseName);
+ portMap.put(baseName, portCount);
+
+ int size = 1;
+ for (int j = 0; j < range_indices_values.size(); j++) {
+ size *= range_indices_values.elementAt(j);
+ }
+ portCount += size;
+ }
+
+ int portId = portMap.get(baseName);
+ for (int j = 0; j < port_indices_values.size(); j++) {
+ int weight = 1;
+ for (int k = j + 1; k < range_indices_values.size(); k++) {
+ weight *= range_indices_values.elementAt(k);
+ }
+ portId += port_indices_values.elementAt(j) * weight;
+ }
+ portMap.put(portName, portId);
+ }
+ }
+
+ for (int i = 0; i < portList.size(); i++) {
+ _portMap.put(portList.elementAt(i),
+ portMap.get(portList.elementAt(i).getName()));
+ }
+ }
+ }
+
+ /**
+ * Gets vector of indices of a string, where the index must be
+ * separated by the specified separator.
+ * examples:
+ * getIndex("name_1_2", "_", 0) will return 1.
+ * getIndex("name_1_2", "_", 1) will return 2.
+ *
+ * @param range string to parse
+ * @param separator delimiter of indices
+ * @return vector of indices
+ */
+ protected Vector<Integer> getIndex(String range, String separator) {
+ Vector<Integer> indices = new Vector<Integer>();
+ String[] subranges = range.split(separator);
+ for (int i = 0; i < subranges.length; i++) {
+ try {
+ int value = Integer.valueOf(subranges[i]);
+ indices.add(value);
+ } catch (Exception e) {
+ continue;
+ }
+ }
+ return indices;
+ }
+
+ public final static int MAX_SPUS = 6;
+ protected HashMap<Port, Integer> _portMap;
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+}
--- /dev/null
+/****************************************************************
+ * COMMON.H
+ * Creator: lschor, 2008-10-30
+ * Description: Specifies some structs and Constants for the CBE-DOL-Implementation
+ *
+ * Revision:
+ * - 2008-10-30: Created
+ */
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "dol.h"
+#include "constant.h"
+
+#define SPE_READ_DEMAND 0
+#define SPE_READ_COMPLETE 1
+#define SPE_COMPLETE 2
+
+// Context for one process --> 384 bit
+typedef struct{
+ uint64_t port_id;
+ uint64_t port_queue_id;
+
+ uint64_t processName; // Address for the name of the process
+ uint64_t processNameLen; // Len of the process Name
+
+ uint32_t number_of_ports;
+ uint32_t is_detached;
+ uint32_t padd[2]; // dummy - for alignment --> It always has to be a multiple of 128 bit!
+} process_context;
+
+// Context for one SPU --> This is send to him!
+typedef struct{
+ uint64_t procContents;
+ uint64_t procContentsLen;
+
+ uint64_t procContentsAll;
+ uint64_t queueFromSPU;
+ uint64_t queueOnSPU;
+
+ uint64_t fifoTails;
+
+ uint64_t ea_base; // Base address of the context
+ uint32_t padd[2]; // dummy - for alignment --> It always has to be a multiple of 128 bit!
+} spu_context;
+
+
+// Create a message to send the queue offset
+// 8 bit: queue number
+// 24 bit: offset of the LS
+#define CREATEQUEUEMESSAGE(_queue, _offset) \
+ ((_queue << 24) | (_offset))
+
+#define QUEUEMSGQUEUE(_message) \
+ ((_message >> 24) & 0xFF)
+
+#define QUEUEMSGOFFSET(_message) \
+ ((_message >> 0) & 0xFFFFFF)
+
+
+// Create the message we like to send, format:
+// 4 bit: code (total 16 possibilities)
+// 9 bit: queue (total 512 possibilities)
+// 19 bit: len
+#define CREATEFASTMESSAGE(_code, _queue, _len) \
+ ((_code << 28) | (_queue << 19) | (_len))
+
+// Get the code from a message
+#define GETFASTCODE(_message) \
+ ((_message >> 28) & 0xF)
+
+// Get the queue from a message
+#define GETFASTQUEUE(_message) \
+ ((_message >> 19) & 0x1FF)
+
+// Get the len from a message
+#define GETFASTLEN(_message) \
+ ((_message >> 0) & 0x7FFFF)
+
+#define MSG_OK 19
+
+// Round a number ot the right DMA number --> Is used for DMA transfers
+uint32_t roundDMA(uint32_t number);
+
+#endif // _COMMON_H_
+
--- /dev/null
+#ifndef __DOL_H__
+#define __DOL_H__
+
+// structure for local memory of process
+typedef struct _local_states *LocalState;
+
+// structure for process
+struct _process;
+
+// standard functions
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr;
+} DOLProcess;
+
+void DOL_read(void *port, void *buf, int len, DOLProcess *process);
+void DOL_write(void *port, void *buf, int len, DOLProcess *process);
+
+unsigned DOL_reserve(void* port, void** destination, unsigned len, DOLProcess* process);
+void DOL_release(void* port, DOLProcess* process);
+unsigned DOL_capture(void* port, void** destination, unsigned len, DOLProcess* process);
+void DOL_consume(void* port, DOLProcess* process);
+
+void DOL_detach(DOLProcess *process);
+int getIndex(const char* string, char* tokens, int indexNumber);
+int *createPort(int *port, int base, int number_of_indices, int index_range_pairs, ...);
+
+#endif
--- /dev/null
+/****************************************************************
+ * Estimation Defintions
+ * Creator: lschor, 2008-11-15
+ * Description: File with includes for time measurements
+ * Principle: if 1 then this point will be measured, if 0 then this point will not be measured
+ *
+ * Revision:
+ * - 2008-11-15: Created
+ */
+
+//
+#ifndef __ESTIMATION_H__
+#define __ESTIMATION_H__
+
+// What to measure?
+//#define MEASURE 0 // Measure activeted
+
+#ifdef MEASURE
+ //#define MEASURE_DOL_READ 0 // Measure DOL READ
+ //#define MEASURE_DOL_READ_FINISH 0 // Measure FINISH DOL Read
+ //#define MEASURE_DOL_READ_START_DMA 0 // Measure Time from start until the DMA process has started
+ //#define MEASURE_DOL_READ_HANDSHAKE 0 // Measure Time of the whole handshake
+ //#define MEASURE_DOL_READ_DMA 0 // Measure Time of DMA Setup
+ //#define MEASURE_DOL_READ_LOCBUF 0 // Measure Time for LocBuf read
+ //#define MEASURE_DOL_READ_DOUBLEBUF 0 // Measure Time for writing into the buffer
+
+ //#define MEASURE_DOL_WRITE 0 // Measure DOL WRITE
+ //#define MEASURE_DOL_WRITE_FINISH 0 // Measure FINISH DOL Write
+ //#define MEASURE_DOL_WRITE_START_DMA 0 // Measure Time from start until the DMA process has started
+ //#define MEASURE_DOL_WRITE_HANDSHAKE 0 // Measure Time of the whole handshake
+ //#define MEASURE_DOL_WRITE_DMA 0 // Measure Time of DMA Setup
+
+ //#define MEASURE_DOL_FIRE 0 // Measure DOL FIRE
+ //#define MEASURE_DOL_INIT 0 // Measure DOL INIT
+ //#define MEASURE_SPE 0 // Measure whole SPE process
+
+ //#define MEASURE_APPLICATION 0 // Measure whole execution time
+ //#define MEASURE_SET_UP_SPE_THREAD 0 // Measure time to set up the SPE-threads
+ //#define MEASURE_SPE_WRITE_DEMAND 0 // Measure time of write demand
+ //#define MEASURE_SPE_READ_DEMAND 0 // Measure time of read demand
+ //#define MEASURE_SPE_WRITE_SUC 0 // Measure time of write successful
+ //#define MEASURE_SPE_READ_SUC 0 // Measure time of read successful
+
+#endif
+
+// Some constants
+#define MEASURE_START 0xFFFFFFFF // Start decrementer at this value
+#define MEASURE_CPU 79800000.0 // Timebase PS3 (in Hz)
+
+#endif
--- /dev/null
+/* -------------------------------------------------------------- */
+/* (C)Copyright 2001,2006, */
+/* International Business Machines Corporation, */
+/* Sony Computer Entertainment, Incorporated, */
+/* Toshiba Corporation, */
+/* */
+/* All Rights Reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or */
+/* without modification, are permitted provided that the */
+/* following conditions are met: */
+/* */
+/* - Redistributions of source code must retain the above copyright*/
+/* notice, this list of conditions and the following disclaimer. */
+/* */
+/* - Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials */
+/* provided with the distribution. */
+/* */
+/* - Neither the name of IBM Corporation nor the names of its */
+/* contributors may be used to endorse or promote products */
+/* derived from this software without specific prior written */
+/* permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
+/* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
+/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
+/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR */
+/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT */
+/* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
+/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
+/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */
+/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR */
+/* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
+/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/* -------------------------------------------------------------- */
+/* PROLOG END TAG zYx */
+#ifndef _FREE_ALIGN_H_
+#define _FREE_ALIGN_H_ 1
+
+#include <stdlib.h>
+
+/* Function
+ *
+ * void free_align(void *ptr)
+ *
+ * Description
+ * The free_align routine frees a memory buffer allocate by the
+ * malloc_align routine. See malloc_align for complete details.
+ */
+
+static __inline void _free_align(void *ptr)
+{
+ void * real;
+
+ if (ptr) {
+ real = *((void **)(ptr)-1);
+ free(real);
+ }
+}
+
+#endif /* _FREE_ALIGN_H_ */
--- /dev/null
+/* -------------------------------------------------------------- */
+/* (C)Copyright 2001,2007, */
+/* International Business Machines Corporation, */
+/* Sony Computer Entertainment, Incorporated, */
+/* Toshiba Corporation, */
+/* */
+/* All Rights Reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or */
+/* without modification, are permitted provided that the */
+/* following conditions are met: */
+/* */
+/* - Redistributions of source code must retain the above copyright*/
+/* notice, this list of conditions and the following disclaimer. */
+/* */
+/* - Redistributions in binary form must reproduce the above */
+/* copyright notice, this list of conditions and the following */
+/* disclaimer in the documentation and/or other materials */
+/* provided with the distribution. */
+/* */
+/* - Neither the name of IBM Corporation nor the names of its */
+/* contributors may be used to endorse or promote products */
+/* derived from this software without specific prior written */
+/* permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND */
+/* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, */
+/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
+/* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR */
+/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT */
+/* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
+/* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
+/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */
+/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR */
+/* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
+/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/* -------------------------------------------------------------- */
+/* PROLOG END TAG zYx */
+
+#ifndef _MALLOC_ALIGN_H_
+#define _MALLOC_ALIGN_H_ 1
+
+#include <stdlib.h>
+
+/* Function
+ *
+ * void * malloc_align(size_t size, unsigned int log2_align)
+ *
+ * Description
+ * The malloc_align routine allocates a memory buffer of <size>
+ * bytes aligned to the power of 2 alignment specified by <log2_align>.
+ * For example, malloc_align(4096, 7) will allocate a memory heap
+ * buffer of 4096 bytes aligned on a 128 byte boundary.
+ *
+ * The aligned malloc routine allocates an enlarged buffer
+ * from the standard memory heap. Space for the real allocated memory
+ * pointer is reserved on the front of the memory buffer.
+ *
+ * ----------------- <--- start of allocated memory
+ * | pad 0 to |
+ * |(1<<log2_align)-1|
+ * | bytes |
+ * |-----------------|
+ * | allocation size |
+ * |-----------------|
+ * | real buffer ptr |
+ * |-----------------|<---- returned aligned memory pointer
+ * | |
+ * | requested |
+ * | memory |
+ * | buffer |
+ * | size |
+ * | bytes |
+ * |_________________|
+ *
+ * Memory allocated by this routine must be freed using the free_align
+ * routine.
+ *
+ * The size of the allocation is saved for special cases where the
+ * data must be mored during a realloc_align.
+ */
+
+static __inline void * _malloc_align(size_t size, unsigned int log2_align)
+{
+ void *ret;
+ char *real;
+ unsigned long offset;
+ unsigned long align;
+
+ align = 1 << log2_align;
+ real = (char *)malloc(size + 2*sizeof(void *) + (align-1));
+ if (real) {
+ offset = (align - (unsigned long)(real + 2*sizeof(void *))) & (align-1);
+ ret = (void *)((real + 2*sizeof(void *)) + offset);
+ *((size_t *)(ret)-2) = size;
+ *((void **)(ret)-1) = (void *)(real);
+ } else {
+ ret = (void *)(real);
+ }
+ return (ret);
+}
+
+#endif /* _MALLOC_ALIGN_H_ */
--- /dev/null
+/*
+ * FastCommunication.cpp / Version PPE
+ *
+ * Created on: Mar 3, 2009
+ * Author: lschor
+ *
+ * For remarks to this file, please refer to the SPE variant.
+ *
+ * Completion of the SPEs:
+ * Is coordinated by this process. Each SPE has to send a request to
+ * the PPE if it is allowed to finish.
+ * If all SPEs have requested to complete, the PPE sends to the SPEs a
+ * message that they can complete, thus return.
+ */
+
+#include "FastCommunication.h"
+
+/*
+ * Constructor
+ */
+FastCommunication::FastCommunication(int nrOfQueues,
+ uint64_t *context_all, uint64_t * ea_ls_base,
+ int32_t * queueFromSPEIn, int32_t * queueOnSPEIn,
+ uint64_t *fifoTails) {
+
+ _context_all = context_all;
+ queueFromSPE = queueFromSPEIn;
+ queueOnSPE = queueOnSPEIn;
+ _ea_ls_base = ea_ls_base;
+ _fifoTails = fifoTails;
+ _nrSpeComplete = 0;
+
+ _nrOfQueues = nrOfQueues;
+ try { _fifos = new fifoCollection[nrOfQueues]; }
+ catch(std::bad_alloc &e) {
+ fprintf(stderr, "[FastCommunication] Memory allocation failure\n");
+ exit(1);
+ }
+
+ for (int i = 0; i < MAXNOREQ; i++) {
+ _request[i].valid = false;
+ }
+}
+
+/*
+ * Deconstructor
+ */
+FastCommunication::~FastCommunication() {
+ delete _fifos;
+}
+
+/*
+ * Register an additional FIFO in the Communication
+ */
+bool FastCommunication::addFifo(int fifoNr, Fifo* fifo, int type,
+ int queue) {
+ _fifos[fifoNr].fifo = fifo;
+ _fifos[fifoNr].queue = queue;
+ _fifos[fifoNr].type = type;
+ _fifos[fifoNr].iswfifo = false;
+
+ // Per FIFO queue, we need two requests, but we can store at max MAXNOREQ of them
+ if (_nrOfRequest < MAXNOREQ) {
+ _nrOfRequest += 2;
+ }
+
+ return true;
+}
+
+/*
+ * Register an additional WindowedFIFO in the Communication
+ */
+bool FastCommunication::addWFifo(int fifoNr, WindowedFifo* wfifo,
+ int type, int queue) {
+ _fifos[fifoNr].wfifo = wfifo;
+ _fifos[fifoNr].queue = queue;
+ _fifos[fifoNr].type = type;
+ _fifos[fifoNr].iswfifo = true;
+
+ // Per FIFO queue, we need two requests, but we can store at max MAXNOREQ of them
+ if (_nrOfRequest < MAXNOREQ) {
+ _nrOfRequest += 2;
+ }
+
+ return true;
+}
+
+/*
+ * Communication: Main update procedure to update
+ */
+bool FastCommunication::update() {
+ // Check if you have received a new message
+ for (int processNr = 0; processNr < NUM_SPES; processNr++) {
+ if (!spe_out_mbox_status((spe_context*) _context_all[processNr]))
+ continue;
+
+ uint32_t messageIn;
+ spe_out_mbox_read((spe_context*) _context_all[processNr],
+ &messageIn, 1);
+
+ uint32_t code = GETFASTCODE(messageIn);
+ uint32_t queue = GETFASTQUEUE(messageIn);
+ uint32_t len = GETFASTLEN(messageIn);
+
+ /***************************************************************************************************************/
+ if (code == SPE_READ_DEMAND) // Have to send a write address (1) --> (2)
+ {
+ // Find out for which fifo the request is
+ fifoCollection *fifocol = NULL;
+ int i;
+ for (i = 0; i < _nrOfQueues; i++) {
+ if (_fifos[i].queue == queue) {
+ fifocol = &_fifos[i];
+ break;
+ }
+ }
+
+ // The queue was not found
+ if (fifocol == NULL) {
+ printf("PPU COM> ERROR, this queue does not exists!\n");
+ return false;
+ }
+
+ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // Windowed FIFO
+ if (_fifos[i].iswfifo) {
+ WindowedFifo* wfifo = NULL;
+ wfifo = _fifos[i].wfifo;
+
+ uint32_t inTail = wfifo->_inTail;
+
+ // This is the len we like to read
+ len = len > (wfifo->unused()) ? wfifo->unused() : len;
+
+ // We can read something
+ if (len > 0) {
+ // Write all information we used to the request-memory
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ // not possible to start a request for this SPE --> Send len = 0
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+ return false;
+ }
+
+ uint64_t baseAddress = _fifoTails[queue] + inTail;
+ while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
+ baseAddress--;
+
+ // Offset
+ uint32_t offset = _fifoTails[queue] + inTail
+ - baseAddress;
+
+ // Store all data in the request buffer
+ request->data = (char *) _malloc_align(roundDMA(len
+ + offset), ALIGNMENT_FACTOR);
+ request->len = len;
+ request->wfifo = wfifo;
+ request->iswfifo = true;
+ request->status = read_started;
+ request->queue = queue;
+ request->offset = offset;
+
+ int ret;
+ do {
+ ret = spe_mfcio_put(
+ (spe_context*) _context_all[processNr],
+ baseAddress, (void *) &(request->data[0]),
+ roundDMA(len + offset), request->tag_id,
+ 0, 0);
+ } while (ret != 0);
+ } else {
+#ifndef STORE_REQUESTS // Send len = 0 back to the sender, this one should try it in a later phase
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+#else // I store the request and may try in a later time to start the transfer
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL)
+ {
+ // not possible to start a request for this SPE --> Send len = 0
+ uint32_t message = CREATEFASTMESSAGE(SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+ return false;
+ }
+
+ request->len = len;
+ request->wfifo = wfifo;
+ request->iswfifo = true;
+ request->status = read_pending;
+ request->queue = queue;
+#endif
+ }
+
+ }
+
+ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // Classic FIFO
+ else {
+ Fifo* fifo = NULL;
+ fifo = _fifos[i].fifo;
+
+ uint32_t inTail = fifo->_inTail;
+
+ // This is the len we like to read
+ len = len > (fifo->unused()) ? fifo->unused() : len;
+
+ // We can read something
+ if (len > 0) {
+ // Write all information we used to the request-memory
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ // not possible to start a request for this SPE --> Send len = 0
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+ return false;
+ }
+
+ uint64_t baseAddress = _fifoTails[queue] + inTail;
+ while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
+ baseAddress--;
+
+ // Offset
+ uint32_t offset = _fifoTails[queue] + inTail
+ - baseAddress;
+
+ // Store all data in the request buffer
+ request->data = (char *) _malloc_align(roundDMA(len
+ + offset), ALIGNMENT_FACTOR);
+ request->len = len;
+ request->fifo = fifo;
+ request->iswfifo = false;
+ request->status = read_started;
+ request->queue = queue;
+ request->offset = offset;
+
+ int ret;
+ do {
+ ret = spe_mfcio_put(
+ (spe_context*) _context_all[processNr],
+ baseAddress, (void *) &(request->data[0]),
+ roundDMA(len + offset), request->tag_id,
+ 0, 0);
+ } while (ret != 0);
+ }
+
+ // Len == 0
+ else {
+#ifndef STORE_REQUESTS // Send len = 0 back to the sender, this one should try it in a later phase
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+#else // I store the request and may try in a later time to start the transfer
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ // not possible to start a request for this SPE --> Send len = 0
+ uint32_t message = CREATEFASTMESSAGE(SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+ return false;
+ }
+
+ request->len = len;
+ request->fifo = fifo;
+ request->iswfifo = false;
+ request->status = read_pending;
+ request->queue = queue;
+#endif
+ }
+ }
+ }
+
+ /***************************************************************************************************************/
+ else if (code == SPE_READ_COMPLETE) // Can finish a write request (4) --> (5)
+ {
+ // Get the stored request
+ comRequest* request = getRequest(read_request_sent, queue);
+
+ if (request == NULL) {
+ printf("PPU Communicate> Couldn't find the request\n");
+ return 0;
+ }
+
+ // Inform my FIFO that the request is completed
+ if (request->iswfifo)
+ request->wfifo->dmaRead(len);
+ else
+ request->fifo->dmaRead(len);
+
+ // Request free
+ deleteRequest(request);
+ }
+
+ /***************************************************************************************************************/
+ else if (code == SPE_COMPLETE) // One SPE has finished
+ {
+ _nrSpeComplete++;
+ }
+ }
+
+ /***************************************************************************************************************/
+ // Check if some active write processes have finished (4)
+ uint8_t req = _currentRequest;
+
+ for (int i = 0; i < _nrOfRequest; i++) {
+ if (_request[req].valid) {
+ if (_request[req].status == read_started) {
+ if (!(testMessage(queueFromSPE[_request[req].queue]) > 0))
+ continue;
+
+ uint32_t tag_id = _request[req].tag_id;
+ uint32_t ret;
+ uint32_t
+ test =
+ spe_mfcio_tag_status_read(
+ (spe_context*) _context_all[queueFromSPE[_request[req].queue]],
+ 0, SPE_TAG_IMMEDIATE, &ret);
+
+ if (((ret & (1 << tag_id)) == 0)) {
+ // Have to write the data into the fifo
+ if (_request[req].iswfifo) { // WFIFO
+
+ _request[req].wfifo->dmaWrite(
+ (char *) _request[req].data
+ + _request[req].offset,
+ _request[req].len);
+ _free_align(_request[req].data);
+
+ // Increase the inTail value (used to know where the last request was started)
+
+ _request[req].wfifo->_inTail
+ = (_request[req].wfifo->_inTail
+ + _request[req].len) % (FIFO_SIZE[_request[req].queue]);
+ } else { // FIFO
+ _request[req].fifo->write(
+ (char *) _request[req].data
+ + _request[req].offset,
+ _request[req].len);
+ _free_align(_request[req].data);
+
+ _request[req].fifo->_inTail
+ = (_request[req].fifo->_inTail
+ + _request[req].len) % (FIFO_SIZE[_request[req].queue]);
+
+ }
+
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, _request[req].queue,
+ _request[req].len);
+ sendMessage(message, queueFromSPE[_request[req].queue]);
+
+ deleteRequest(&_request[req]);
+ _currentRequest = (req + 1) % _nrOfRequest;
+
+ break;
+ }
+ } else if (_request[req].status == read_pending) { // Has an open request for sending
+
+ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // Windowed FIFO
+ if (_request[req].iswfifo) {
+
+ if (_request[req].wfifo->unused() > 0) {
+ comRequest *request = &_request[req];
+
+ // This is the len we like to read
+ uint32_t len = request->len > (request->wfifo->unused()) ? request->wfifo->unused()
+ : request->len;
+
+ uint32_t inTail = request->wfifo->_inTail;
+ uint64_t baseAddress = _fifoTails[request->queue]
+ + inTail;
+
+ while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
+ baseAddress--;
+
+ // Offset --> How much we had to align
+ uint32_t offset = _fifoTails[request->queue]
+ + inTail - baseAddress;
+
+ request->data = (char *) _malloc_align(roundDMA(
+ len + offset), ALIGNMENT_FACTOR);
+ request->len = len;
+ request->status = read_started;
+ request->offset = offset;
+
+ // Set up the request in the MFC
+ int ret;
+ do {
+ ret = spe_mfcio_put(
+ (spe_context*) _context_all[queueFromSPE[_request[req].queue]],
+ baseAddress,
+ (void *) &(request->data[0]),
+ roundDMA(len + offset),
+ request->tag_id, 0, 0);
+ } while (ret != 0);
+ }
+ }
+
+ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // Classic FIFO
+ else {
+
+ if (_request[req].fifo->unused() > 0) {
+ comRequest *request = &_request[req];
+
+ // This is the len we like to read
+ uint32_t len = request->len > (request->fifo->unused()) ? request->fifo->unused() : request->len;
+
+ uint32_t inTail = request->fifo->_inTail;
+ uint64_t baseAddress = _fifoTails[request->queue]
+ + inTail;
+
+ while (baseAddress % 16 != 0)
+ baseAddress--;
+
+ // Offset
+ uint32_t offset = _fifoTails[request->queue]
+ + inTail - baseAddress;
+
+ // Store all data in the request buffer
+ request->data = (char *) _malloc_align(roundDMA(
+ len + offset), ALIGNMENT_FACTOR);
+ request->len = len;
+ request->status = read_started;
+ request->offset = offset;
+
+ // Start the DMA transfer
+ int ret;
+ do {
+ ret
+ = spe_mfcio_put(
+ (spe_context*) _context_all[queueFromSPE[_request[req].queue]],
+ baseAddress,
+ (void *) &(request->data[0]),
+ roundDMA(len + offset),
+ request->tag_id, 0, 0);
+ } while (ret != 0);
+ }
+ }
+ }
+ }
+ req = (req + 1) % _nrOfRequest;
+ }
+
+ /***************************************************************************************************************/
+ // Have some out - queue some data to send
+ for (int i = 0; i < _nrOfQueues; i++) {
+ if (_fifos[i].type == this->out) {
+ if (_fifos[i].iswfifo) { // WFIFO
+ // Start only a write process if there is really enough place in the outbound mailbox
+ if (_fifos[i].wfifo->dmaAllowed()
+ && _fifos[i].wfifo->used() > 0) {
+ uint32_t queue = _fifos[i].queue;
+
+ // Can we send a message to this processor or is it blocked?
+ if (testMessage(queueOnSPE[queue]) <= 0) {
+ continue;
+ }
+
+ // Write all information we used to the request-memory
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ } else {
+ uint32_t len = _fifos[i].wfifo->dmaStart();
+ // Create a write-demand message
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_DEMAND, queue, len);
+
+ request->len = len;
+ request->queue = queue;
+ request->status = read_request_sent;
+ request->wfifo = _fifos[i].wfifo;
+ request->iswfifo = true;
+
+ sendMessage(message, queueOnSPE[queue]);
+ }
+ break;
+ }
+ } else { // FIFO
+ // Start only a write process if there is really enough place in the outbound mailbox
+ if (_fifos[i].fifo->dmaAllowed() && _fifos[i].fifo->used()
+ > 0) {
+ uint32_t queue = _fifos[i].queue;
+
+ if (testMessage(queueOnSPE[queue]) <= 0)
+ continue;
+
+ // Write all information we used to the request-memory
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ } else {
+ uint32_t len = _fifos[i].fifo->dmaStart();
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_DEMAND, queue, len);
+ request->len = len;
+ request->queue = queue;
+ request->status = read_request_sent;
+ request->fifo = _fifos[i].fifo;
+ request->iswfifo = false;
+
+ sendMessage(message, queueOnSPE[queue]);
+ }
+ break;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+/*
+ * Create a new request to store in the cache
+ *
+ */
+comRequest* FastCommunication::newRequest() {
+ for (int i = 0; i < _nrOfRequest; i++) {
+ if (!_request[i].valid) {
+ _request[i].tag_id = i + 3;
+ _request[i].valid = true;
+ return &(_request[i]);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Delete the request
+ *
+ */
+void FastCommunication::deleteRequest(comRequest* request) {
+ request->valid = false;
+ request->tag_id = 0;
+}
+
+/*
+ * Returns the request one like to get
+ */
+comRequest* FastCommunication::getRequest(uint8_t status, uint32_t queue) {
+ uint8_t req = _currentRequest;
+
+ for (int i = 0; i < _nrOfRequest; i++) {
+ if (_request[req].valid && _request[req].status == status
+ && _request[req].queue == queue) {
+ _currentRequest = (req + 1) % _nrOfRequest;
+ return &(_request[req]);
+ }
+ req = (req + 1) % _nrOfRequest;
+ }
+
+ return NULL;
+}
+
+/**
+ * True if no communication is necessary, false if there is active communication
+ */
+bool FastCommunication::empty() { /////////////////////////////////////////////////////////////////
+ // check if one fifo would like to send something to another SPE
+ for (int i = 0; i < _nrOfQueues; i++) {
+ if (_fifos[i].type == this->out) {
+ if (_fifos[i].iswfifo) { // WFIFO
+ if (_fifos[i].wfifo->used() > 0)
+ {
+ return false;
+ }
+ } else {
+ if (_fifos[i].fifo->used() > 0)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ // are open sendings?
+ for (int i = 0; i < _nrOfRequest; i++) {
+ if (_request[i].valid) {
+ return false;
+ }
+ }
+
+ if (_nrSpeComplete < NUM_SPES) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Send a message to a SPE
+ */
+void FastCommunication::sendMessage(uint32_t message, int32_t process) {
+ spe_in_mbox_write((spe_context*) _context_all[process],
+ (uint32_t*) &message, 1, SPE_MBOX_ANY_NONBLOCKING);
+}
+
+/**
+ * Test if we can send a message to an SPE without stalling
+ */
+int FastCommunication::testMessage(int32_t process) {
+ return spe_in_mbox_status((spe_context*) _context_all[process]);
+}
+
--- /dev/null
+/*
+ * Communication.h
+ *
+ * Created on: Mar 3, 2009
+ * Author: lschor
+ */
+
+#ifndef FASTCOMMUNICATION_H_
+#define FASTCOMMUNICATION_H_
+
+// System includes
+#include "cbe_mfc.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <sys/time.h>
+#include <stddef.h>
+#include <libspe2.h>
+#include <pthread.h>
+
+// Local includes
+#include "lib/ppu/common_ppu.h"
+#include "Fifo.h"
+#include "WindowedFifo.h"
+#include "../common.h"
+
+
+// Include to allocate/free using for DMA transfers
+#include "../lib/malloc_align.h"
+#include "../lib/free_align.h"
+
+//Cell Macros
+#define waittag(tag_id) mfc_write_tag_mask(1<<tag_id); mfc_read_tag_status_all();
+
+#define MAXNOREQ 24
+
+// A request
+typedef struct _comRequest {
+ bool valid; // If the request is valid
+ uint32_t status; // Status of the request (write_request_sen, ...)
+
+ uint32_t tag_id; // Tag ID
+ uint32_t queue; // The queue which is used by the request
+
+ bool iswfifo; // True if it is a WFIFO
+ Fifo* fifo; // Pointer to the used FIFO
+ WindowedFifo* wfifo; // Pointer to the WFIFO
+
+ uint32_t len; // The len of the data
+ char* data; // Point to the data which are stored
+ uint32_t offset;
+} comRequest;
+
+typedef struct _fifoCollection {
+ int type; // local, in or out
+ int queue; // Corresponding queue number
+
+ bool iswfifo; // True if it is a WFIFO
+ WindowedFifo* wfifo; // Pointer to the WFIFO
+ Fifo* fifo; // Pointer to the FIFO
+} fifoCollection;
+
+/**
+ * The Communication Class
+ */
+class FastCommunication {
+public:
+ FastCommunication(int nrOfQueues, uint64_t *context_all, uint64_t *ea_base_all, int32_t * queueFromSPE, int32_t * queueOnSPE, uint64_t *);
+ virtual ~FastCommunication();
+
+ bool addFifo(int fifoNr, Fifo* fifo, int type, int queue);
+ bool addWFifo(int fifoNr, WindowedFifo* fifo, int type, int queue);
+
+ bool update();
+ bool empty();
+
+ static int const local = 0;
+ static int const in = 1;
+ static int const out = 2;
+
+ static int const comIn = 0;
+ static int const comOut = 1;
+
+ static int const read_request_sent = 0;
+ static int const read_started = 1;
+ static int const read_pending = 2;
+
+protected:
+ void sendMessage(uint32_t message, int32_t process);
+ int testMessage(int32_t process);
+
+ comRequest* newRequest();
+ void deleteRequest(comRequest* request);
+ comRequest* getRequest(uint8_t status, uint32_t queue);
+
+ int _nrOfRequest;
+ comRequest _request[MAXNOREQ];
+ uint8_t _currentRequest;
+
+ int _nrOfQueues;
+ fifoCollection * _fifos;
+
+ uint64_t _ea_base;
+ uint64_t * _context_all;
+ int32_t * queueFromSPE;
+ int32_t * queueOnSPE;
+ uint64_t * _ea_ls_base;
+ uint64_t * _fifoTails;
+
+ // This is used to check the completion of the SPEs (See remarks in FifoCommunication.cpp)
+ uint8_t _nrSpeComplete;
+
+};
+
+#endif /* FASTCOMMUNICATION_H_ */
--- /dev/null
+#include "Fifo.h"
+
+/**
+ *
+ */
+Fifo::Fifo(unsigned size = 18) {
+ //except at the beginning, _head and _tail must never overlap,
+ //otherwise one does not know whether the buffer is full or
+ //empty. To have nevertheless a buffer with the given capacity,
+ //a buffer with one more element is allocated.
+ _size = size;
+ _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR);
+ if(!_buffer) {
+ fprintf(stderr,"[FIFO] Memory allocation failure\n");
+ exit(-1);
+ }
+
+ _tail = 0;
+ _pos = 0;
+ _blocked = 0;
+
+ _inTail = 0;
+ _activeDMA = false;
+}
+
+/**
+ *
+ */
+Fifo::~Fifo() {
+ if (_buffer) {
+ _free_align(_buffer);
+ }
+ _buffer = 0;
+ _tail = 0;
+ _pos = 0;
+}
+
+/**
+ *
+ */
+unsigned Fifo::read(void *destination, unsigned len) {
+ char* buffer = (char*) destination;
+ unsigned read = (len <= used() ? len : used());
+
+ if (_tail + read < _size) {
+ memcpy(buffer, _buffer + _tail, read);
+ } else {
+ memcpy(buffer, _buffer + _tail, _size - _tail);
+ memcpy(buffer + _size - _tail, _buffer, read - _size + _tail);
+ }
+
+ _tail = ((unsigned) (_tail + read) % _size);
+ _pos -= read;
+ return read;
+}
+
+/**
+ *
+ */
+unsigned Fifo::write(const void *source, unsigned len) {
+
+ char* buffer = (char*) source;
+ unsigned write = (len <= unused() ? len : unused());
+ unsigned head = (_tail + _pos) % _size;
+
+ if (head + write < _size) {
+ memcpy(_buffer + head, buffer, write);
+ } else {
+ memcpy(_buffer + head, buffer, _size - head);
+ memcpy(_buffer, buffer + _size - head, write - _size + head);
+ }
+
+ _pos += write;
+ return write;
+}
+
+/**
+ * Size of this fifo
+ */
+unsigned Fifo::size() const {
+ return (_size);
+}
+
+/**
+ * How many bytes are currently free in the buffer
+ */
+unsigned Fifo::unused() const {
+ return (_size) - used();
+}
+
+/**
+ * How many data are currently stored in the fifo
+ */
+unsigned Fifo::used() const {
+ return _pos;
+}
+
+/*
+ * Get the pointer to the start of the queue
+ */
+char *Fifo::getQueuePointer() {
+ return _buffer;
+}
+
+/*
+ * Has completed a dma read process, i.e. has read out of the queue
+ */
+void Fifo::dmaRead(unsigned len) {
+ _activeDMA = false;
+
+ if (len == 0) {
+ _blocked = BLOCKED_MAX_NR;
+ } else {
+ _tail = ((unsigned) (_tail + len) % _size);
+ _pos -= len;
+ }
+}
+
+/*
+ * Start a DMA request, returns the current space one have
+ */
+unsigned Fifo::dmaStart() {
+ _activeDMA = true;
+
+ if (_tail + _pos > _size) {
+ return _size - _tail;
+ } else {
+ return _pos;
+ }
+}
+
+/*
+ * Is allowed to start a dma request
+ */
+bool Fifo::dmaAllowed() {
+ if (_blocked > 0) {
+ _blocked--;
+ return false;
+ } else {
+ return !_activeDMA;
+ }
+}
--- /dev/null
+#ifndef _FIFO_H_
+#define _FIFO_H_
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../constant.h"
+
+#include "../lib/malloc_align.h"
+#include "../lib/free_align.h"
+
+/**
+ * FIFO Class: For remarks see SPE
+ */
+class Fifo {
+ public:
+ Fifo(unsigned size);
+ virtual ~Fifo();
+
+ virtual unsigned read(void *destination, unsigned len);
+ virtual unsigned write(const void *source, unsigned len);
+
+ virtual unsigned used() const;
+ virtual unsigned unused() const;
+ virtual unsigned size() const;
+
+ virtual char *getQueuePointer();
+ virtual void dmaRead(unsigned len);
+ virtual unsigned dmaStart();
+ virtual bool dmaAllowed();
+
+ unsigned _inTail;
+
+ protected:
+ char *_buffer;
+
+ unsigned _tail;
+ unsigned _pos;
+ unsigned _size;
+
+ unsigned _blocked;
+ bool _activeDMA;
+};
+
+#endif
--- /dev/null
+#include "ProcessWrapper.h"
+
+/**
+ *
+ */
+ProcessWrapper::ProcessWrapper(char* name, int iteratorIndex[4]) {
+ //copy name, deliberately avoid using strlen and strcpy for code size
+ //minimization
+ int nameLength = 0;
+ while (name[nameLength] != 0) {
+ nameLength++;
+ }
+ _name = new char[nameLength + 1];
+ for (int i = 0; i < nameLength; i++) {
+ _name[i] = name[i];
+ }
+
+ _isDetached = false;
+ for (int i = 0; i < 4; i++) {
+ _iteratorIndex[i] = iteratorIndex[i];
+ }
+
+ readPos = 0;
+ writePos = 0;
+}
+
+/**
+ *
+ */
+ProcessWrapper::~ProcessWrapper() {
+ if (_name) {
+ delete _name;
+ }
+}
+
+/**
+ *
+ */
+void ProcessWrapper::init() {
+ _process.init(&_process);
+}
+
+/**
+ *
+ */
+int ProcessWrapper::fire() {
+ return _process.fire(&_process);
+}
+
+/**
+ *
+ */
+void ProcessWrapper::detach() {
+ _isDetached = true;
+}
+
+/**
+ * Get the index of this process.
+ * @param indexNumber position of index (starting at 0)
+ */
+int ProcessWrapper::getIndex(unsigned indexNumber) const {
+ if (indexNumber < 4) {
+ return _iteratorIndex[indexNumber];
+ }
+ return -1;
+}
--- /dev/null
+#ifndef _PROCESSWRAPPER_H_
+#define _PROCESSWRAPPER_H_
+
+#include <dol.h>
+
+/**
+ * Process Wrapper Class
+ */
+class ProcessWrapper
+{
+ public:
+ ProcessWrapper(char* name, int iteratorIndex[4]);
+ virtual ~ProcessWrapper();
+
+ virtual void init();
+ virtual int fire();
+ virtual bool isDetached() { return _isDetached; }
+ virtual void detach();
+ virtual int getIndex(unsigned indexNumber) const;
+
+ // Positions for read and write operations which are blocked by Protothread
+ unsigned int readPos;
+ unsigned int writePos;
+
+ protected:
+ char* _name;;
+ DOLProcess _process;
+ bool _isDetached;
+ int _iteratorIndex[4];
+};
+
+#endif
--- /dev/null
+#include "WindowedFifo.h"
+
+/**
+ *
+ */
+WindowedFifo::WindowedFifo(unsigned size = 20) {
+ //std::cout << "Create WindowedFifo." << std::endl;
+ _size = size;
+ _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR);
+ if(!_buffer) {
+ fprintf(stderr,"[WFIFO] Memory allocation failure\n");
+ exit(-1);
+ }
+
+ _head = 0;
+ _tail = 0;
+
+ _headRoom = 0;
+ _tailRoom = 0;
+ _use = 0;
+ _blocked = 0;
+
+ _isHeadReserved = false;
+ _isTailReserved = false;
+ _activeDMA = false;
+}
+
+/**
+ *
+ */
+WindowedFifo::~WindowedFifo() {
+ if (_buffer) {
+ _free_align(_buffer);
+ }
+ _buffer = 0;
+ _head = 0;
+ _tail = 0;
+ _use = 0;
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::reserve(void** dest, unsigned len) {
+ char** destination = (char**) dest;
+ //std::cout << "Attempt to reserve " << len << " bytes." << std::endl;
+
+ //can only reserve one piece at a time
+ if (_isHeadReserved) {
+ *destination = 0;
+ return 0;
+ }
+
+ //reserve at most as much memory as still available in the buffer
+ unsigned write = (len <= _size - _use ? len : _size - _use);
+
+ if (write > 0) {
+ //if wrap-around in buffer: return only buffer for the
+ //contiguous buffer space
+ if (_head + write > _size) {
+ write = _size - _head;
+ }
+
+ _headRoom = (_head + write) == _size ? 0 : _head + write;
+ *destination = &(_buffer[_head]);
+ _isHeadReserved = true;
+ }
+
+ //std::cout << "Reserved " << write << " bytes." << std::endl;
+ _writeReserve = write;
+ return write;
+}
+
+/**
+ *
+ */
+void WindowedFifo::release() {
+ if (_isHeadReserved) {
+ //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl;
+ _head = _headRoom;
+ _use += _writeReserve;
+ _isHeadReserved = false;
+ }
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::capture(void **dest, unsigned len) {
+ char** destination = (char**) dest;
+ //std::cout << "Attempt to capture " << len << " bytes." << std::endl;
+
+ if (_isTailReserved) {
+ //std::cout << "Only one attempt to capture allowed." << std::endl;
+ *destination = 0;
+ return 0;
+ }
+
+ //capture at most as much data as available in the buffer
+ unsigned read = (len <= _use ? len : _use);
+
+ if (read > 0) {
+ //if wrap-around in buffer: return only buffer for the
+ //conntiguous buffer space
+ if (_tail + read > _size) {
+ read = _size - _tail;
+ }
+
+ _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read;
+ *destination = &(_buffer[_tail]);
+ _isTailReserved = true;
+ }
+
+ //std::cout << "Captured " << read << " bytes." << std::endl;
+ _readReserve = read;
+ return read;
+}
+
+/**
+ *
+ */
+void WindowedFifo::consume() {
+ if (_isTailReserved) {
+ //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl;
+ _tail = _tailRoom;
+ _use -= _readReserve;
+ _isTailReserved = false;
+ }
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::size() const {
+ return _size;
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::unused() const {
+ return _size - _use;
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::used() const {
+ return _use;
+}
+
+/*
+ * Get the pointer to the start of the queue
+ */
+char *WindowedFifo::getQueuePointer() {
+ return _buffer;
+}
+
+/*
+ * Has completed a dma read process, i.e. has read out of the queue
+ */
+void WindowedFifo::dmaRead(unsigned len) {
+ _activeDMA = false;
+
+ if (len == 0) {
+ _blocked = BLOCKED_MAX_NR;
+ } else {
+ _tail = ((unsigned) (_tail + len) % _size);
+ _use -= len;
+ }
+}
+
+/*
+ * Start a DMA request, returns the current space one have
+ */
+unsigned WindowedFifo::dmaStart() {
+ _activeDMA = true;
+
+ // If we go over the end, we only take as much as is on one side!
+ //return used();
+
+ if (_tail + _use > _size) {
+ return _size - _tail;
+ } else {
+ return _use;
+ }
+}
+
+/*
+ * Is allowed to start a dma request
+ */
+bool WindowedFifo::dmaAllowed() {
+#ifndef STORE_REQUESTS
+ if (_blocked > 0) {
+ _blocked--;
+ return false;
+ } else {
+ return !_activeDMA;
+ }
+#else
+ return !_activeDMA;
+#endif
+}
+
+/**
+ * Is needed for DMA transfers
+ */
+unsigned WindowedFifo::dmaWrite(const void *source, unsigned len) {
+
+ char* buffer = (char*) source;
+
+ if (_head + len < _size) {
+ memcpy(_buffer + _head, buffer, len);
+ } else {
+ // We should never be here!
+ memcpy(_buffer + _head, buffer, _size - _head);
+ memcpy(_buffer, buffer + _size - _head, len - _size + _head);
+ }
+ _use += len;
+ _head = (_head + len) >= _size ? _head + len - _size : _head + len;
+
+ return len;
+}
--- /dev/null
+#ifndef _WINDOWEDFIFO_H_
+#define _WINDOWEDFIFO_H_
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../constant.h"
+
+#include "../lib/malloc_align.h"
+#include "../lib/free_align.h"
+
+class WindowedFifo {
+ public:
+ WindowedFifo(unsigned size);
+ virtual ~WindowedFifo();
+
+ // Write
+ virtual unsigned reserve(void** destination, unsigned len);
+ virtual void release();
+
+ // Read
+ virtual unsigned capture(void** destination, unsigned len);
+ virtual void consume();
+
+ // General FIFO functions
+ virtual unsigned used() const;
+ virtual unsigned unused() const;
+ virtual unsigned size() const;
+
+ // DMA functions
+ virtual char *getQueuePointer();
+ virtual void dmaRead(unsigned len);
+ virtual unsigned dmaStart();
+ virtual bool dmaAllowed();
+ virtual unsigned dmaWrite(const void *source, unsigned len);
+
+ // Global variables
+ unsigned _inTail;
+ protected:
+ char *_buffer;
+
+ unsigned _head;
+ unsigned _tail;
+ unsigned _headRoom;
+ unsigned _tailRoom;
+
+ unsigned _size;
+ unsigned _use;
+
+ unsigned _writeReserve;
+ unsigned _readReserve;
+
+ bool _isHeadReserved;
+ bool _isTailReserved;
+
+ unsigned _blocked; // Blocked number the request has to wait
+ bool _activeDMA; // Is there an active DMA on this buffer
+
+};
+
+#endif
--- /dev/null
+/*
+ * common.cpp
+ *
+ * Created on: Feb 27, 2009
+ * Author: lschor
+ */
+
+#include "../common.h"
+
+/**
+ * Aligend a number to to the data bus
+ */
+uint32_t roundDMA(uint32_t number)
+{
+ if (number > 16)
+ if (number % 16 == 0) return number;
+ else return number + 16 - (number % 16);
+ else if (number > 8)
+ return 16;
+ else if (number > 4)
+ return 8;
+ else if (number > 2)
+ return 4;
+ else if (number > 1)
+ return 2;
+ else
+ return 1;
+}
--- /dev/null
+/****************************************************************
+ * Common structs for the PPU
+ * Creator: lschor, 2008-11-21
+ * Description: Common structs for the PPU
+ *
+ * Revision:
+ * - 2008-11-21: Created
+ */
+
+#ifndef __COMMON_PPU_H__
+#define __COMMON_PPU_H__
+
+#include <libspe2.h>
+
+// data structure for running SPE thread
+typedef struct spu_data {
+ spe_context_ptr_t spe_ctx;
+ pthread_t pthread;
+ void *argp;
+} spu_data_t;
+
+// Struct for a process
+typedef struct _process_data {
+ uint64_t *procContentsAll;
+ int32_t *queueFromSPU;
+ int32_t *queueOnSPU;
+ uint64_t *ea_ls_base;
+ uint64_t *fifoTails;
+} ProcessData;
+
+
+#endif
--- /dev/null
+#include "dolSupport.h"\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned read(void* fifo, void* buf, unsigned len, DOLProcess* p) {\r
+ unsigned int\r
+ pos =\r
+ static_cast<ProcessWrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->readPos;\r
+ pos += ((Fifo*) fifo)->read((char *) buf + pos, len - pos);\r
+\r
+ if (pos == len)\r
+ static_cast<ProcessWrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->readPos\r
+ = 0;\r
+ else\r
+ static_cast<ProcessWrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->readPos\r
+ = pos;\r
+ return pos;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned write(void* fifo, void* buf, unsigned len, DOLProcess* p) {\r
+ unsigned int\r
+ pos =\r
+ static_cast<ProcessWrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->writePos;\r
+ pos += ((Fifo*) fifo)->write((char *) buf + pos, len - pos);\r
+\r
+ if (pos == len)\r
+ static_cast<ProcessWrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->writePos\r
+ = 0;\r
+ else\r
+ static_cast<ProcessWrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->writePos\r
+ = pos;\r
+ return pos;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned reserve(void* fifo, void** destination, unsigned len,\r
+ DOLProcess* p) {\r
+ return ((WindowedFifo*) fifo)->reserve(destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void release(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*) fifo)->release();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned capture(void* fifo, void** destination, unsigned len,\r
+ DOLProcess* p) {\r
+ return ((WindowedFifo*) fifo)->capture(destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void consume(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*) fifo)->consume();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void DOL_detach(DOLProcess* p) {\r
+ static_cast<ProcessWrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->detach();\r
+}\r
+\r
+void createPort(void** port, void* base, int number_of_indices,\r
+ int index0, int range0) {\r
+ *port = (void**) ((void**) base)[index0];\r
+}\r
+\r
+void createPort(void** port, void* base, int number_of_indices,\r
+ int index0, int range0, int index1, int range1) {\r
+ *port = (void**) ((void**) base)[index0 * range1 + index1];\r
+}\r
+\r
+void createPort(void** port, void* base, int number_of_indices,\r
+ int index0, int range0, int index1, int range1, int index2,\r
+ int range2) {\r
+ *port = (void**) ((void**) base)[index0 * range1 * range2 + index1\r
+ * range2 + index2];\r
+}\r
+\r
+void createPort(void** port, void* base, int number_of_indices,\r
+ int index0, int range0, int index1, int range1, int index2,\r
+ int range2, int index3, int range3) {\r
+ *port = (void**) ((void**) base)[index0 * range1 * range2 * range3\r
+ + index1 * range2 * range3 + index2 * range3 + index3];\r
+}\r
--- /dev/null
+#ifndef DOLSUPPORT_H\r
+#define DOLSUPPORT_H\r
+\r
+#include "dol.h"\r
+#include "pt.h"\r
+\r
+#include "ProcessWrapper.h"\r
+\r
+#include "Fifo.h"\r
+#include "WindowedFifo.h"\r
+\r
+typedef struct _process_data {\r
+ int lc;\r
+ ProcessWrapper *wrapper;\r
+} process_data;\r
+\r
+\r
+#define DOL_read(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), read(port, buf, size, process) == size);\r
+\r
+#define DOL_write(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), write(port, buf, size, process) == size);\r
+\r
+#define DOL_reserve(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), reserve(port, (void**)buf, size, process) == size);\r
+\r
+#define DOL_release(port, process) \\r
+ release(port, process);\r
+\r
+#define DOL_capture(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), capture(port, (void**)buf, size, process) == size);\r
+\r
+#define DOL_consume(port, process) \\r
+ consume(port, process);\r
+\r
+void DOL_detach(DOLProcess* p);\r
+\r
+//macros to deal with iterated ports\r
+/**\r
+ * macro to create a variable to store a port name\r
+ *\r
+ * @param name name of the variable\r
+ */\r
+#define CREATEPORTVAR(name) static Fifo *name\r
+\r
+/**\r
+ * Create the port name of an iterated port based on its basename and the\r
+ * given indices.\r
+ *\r
+ * @param port buffer where the result is stored (created using\r
+ * CREATEPORTVAR)\r
+ * @param base basename of the port\r
+ * @param number_of_indices number of dimensions of the port\r
+ * @param index_range_pairs index and range values for each dimension\r
+ */\r
+\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+ createPort((void**)(&port), base, number_of_indices, index_range_pairs)\r
+\r
+#define GETINDEX(dimension) \\r
+ static_cast<ProcessWrapper *>((static_cast<process_data *>(p->wptr))->wrapper)->getIndex(dimension)\r
+\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1, int index2, int range2);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1, int index2, int range2, int index3, int range3);\r
+\r
+//fifo access functions\r
+unsigned write(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+unsigned read(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+\r
+//windowed fifo access functions\r
+unsigned reserve(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+void release(void* fifo, DOLProcess* p);\r
+unsigned capture(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+void consume(void* fifo, DOLProcess* p);\r
+\r
+#endif\r
--- /dev/null
+/****************************************************************
+ * Header for the main function
+ * Creator: lschor, 2008-11-21
+ * Description: Header file for the main function of the PPU
+ *
+ * Revision:
+ * - 2008-11-21: Created
+ */
+
+#ifndef __PPU_MAIN_H__
+#define __PPU_MAIN_H__
+
+// System includes
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <libspe2.h>
+#include <pthread.h>
+
+// Local includes
+#include "lib/malloc_align.h"
+#include "lib/free_align.h"
+#include "lib/common.h"
+#include "lib/estimation.h"
+#include "lib/ppu/common_ppu.h"
+#include "cbe_mfc.h"
+
+// Program context for the Processes
+volatile process_context ctx_proc[NUM_PROCS_SPU] __attribute__ ((aligned(16)));
+
+// Program context for the SPEs
+volatile spu_context ctx_spu[NUM_SPES] __attribute__ ((aligned(16)));
+
+// The SPE-program-handler
+spe_program_handle_t *program[NUM_SPES];
+
+// Data for the SPEs
+spu_data_t data[NUM_SPES];
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-addrlabels.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on the "Labels as
+ * values" feature of gcc
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations is based on a special
+ * feature of the GCC C compiler called "labels as values". This
+ * feature allows assigning pointers with the address of the code
+ * corresponding to a particular C label.
+ *
+ * For more information, see the GCC documentation:
+ * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+ *
+ */
+
+#ifndef __LC_ADDRLABELS_H__
+#define __LC_ADDRLABELS_H__
+
+/** \hideinitializer */
+typedef void * lc_t;
+
+#define LC_INIT(s) s = NULL
+
+#define LC_RESUME(s) \
+ do { \
+ if(s != NULL) { \
+ goto *s; \
+ } \
+ } while(0)
+
+#define LC_CONCAT2(s1, s2) s1##s2
+#define LC_CONCAT(s1, s2) LC_CONCAT2(s1, s2)
+
+#define LC_SET(s) \
+ do { \
+ LC_CONCAT(LC_LABEL, __LINE__): \
+ (s) = &&LC_CONCAT(LC_LABEL, __LINE__); \
+ } while(0)
+
+#define LC_END(s)
+
+#endif /* __LC_ADDRLABELS_H__ */
+/** @} */
--- /dev/null
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-switch.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on switch() statment
+ * \author Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations uses the C switch()
+ * statement to resume execution of a function somewhere inside the
+ * function's body. The implementation is based on the fact that
+ * switch() statements are able to jump directly into the bodies of
+ * control structures such as if() or while() statmenets.
+ *
+ * This implementation borrows heavily from Simon Tatham's coroutines
+ * implementation in C:
+ * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+ */
+
+#ifndef __LC_SWITCH_H__
+#define __LC_SWITCH_H__
+
+/* WARNING! lc implementation using switch() does not work if an
+ LC_SET() is done within another switch() statement! */
+
+/** \hideinitializer */
+typedef unsigned short lc_t;
+
+#define LC_INIT(s) s = 0;
+
+#define LC_RESUME(s) switch(s) { case 0:
+
+#define LC_SET(s) s = __LINE__; case __LINE__:
+
+#define LC_END(s) }
+
+#endif /* __LC_SWITCH_H__ */
+
+/** @} */
--- /dev/null
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \defgroup lc Local continuations
+ * @{
+ *
+ * Local continuations form the basis for implementing protothreads. A
+ * local continuation can be <i>set</i> in a specific function to
+ * capture the state of the function. After a local continuation has
+ * been set can be <i>resumed</i> in order to restore the state of the
+ * function at the point where the local continuation was set.
+ *
+ *
+ */
+
+/**
+ * \file lc.h
+ * Local continuations
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifdef DOXYGEN
+/**
+ * Initialize a local continuation.
+ *
+ * This operation initializes the local continuation, thereby
+ * unsetting any previously set continuation state.
+ *
+ * \hideinitializer
+ */
+#define LC_INIT(lc)
+
+/**
+ * Set a local continuation.
+ *
+ * The set operation saves the state of the function at the point
+ * where the operation is executed. As far as the set operation is
+ * concerned, the state of the function does <b>not</b> include the
+ * call-stack or local (automatic) variables, but only the program
+ * counter and such CPU registers that needs to be saved.
+ *
+ * \hideinitializer
+ */
+#define LC_SET(lc)
+
+/**
+ * Resume a local continuation.
+ *
+ * The resume operation resumes a previously set local continuation, thus
+ * restoring the state in which the function was when the local
+ * continuation was set. If the local continuation has not been
+ * previously set, the resume operation does nothing.
+ *
+ * \hideinitializer
+ */
+#define LC_RESUME(lc)
+
+/**
+ * Mark the end of local continuation usage.
+ *
+ * The end operation signifies that local continuations should not be
+ * used any more in the function. This operation is not needed for
+ * most implementations of local continuation, but is required by a
+ * few implementations.
+ *
+ * \hideinitializer
+ */
+#define LC_END(lc)
+
+/**
+ * \var typedef lc_t;
+ *
+ * The local continuation type.
+ *
+ * \hideinitializer
+ */
+#endif /* DOXYGEN */
+
+#ifndef __LC_H__
+#define __LC_H__
+
+
+#ifdef LC_INCLUDE
+#include LC_INCLUDE
+#else
+#include "lc-switch.h"
+#endif /* LC_INCLUDE */
+
+#endif /* __LC_H__ */
+
+/** @} */
+/** @} */
--- /dev/null
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: pt-sem.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \defgroup ptsem Protothread semaphores
+ * @{
+ *
+ * This module implements counting semaphores on top of
+ * protothreads. Semaphores are a synchronization primitive that
+ * provide two operations: "wait" and "signal". The "wait" operation
+ * checks the semaphore counter and blocks the thread if the counter
+ * is zero. The "signal" operation increases the semaphore counter but
+ * does not block. If another thread has blocked waiting for the
+ * semaphore that is signalled, the blocked thread will become
+ * runnable again.
+ *
+ * Semaphores can be used to implement other, more structured,
+ * synchronization primitives such as monitors and message
+ * queues/bounded buffers (see below).
+ *
+ * The following example shows how the producer-consumer problem, also
+ * known as the bounded buffer problem, can be solved using
+ * protothreads and semaphores. Notes on the program follow after the
+ * example.
+ *
+ \code
+#include "pt-sem.h"
+
+#define NUM_ITEMS 32
+#define BUFSIZE 8
+
+static struct pt_sem mutex, full, empty;
+
+PT_THREAD(producer(struct pt *pt))
+{
+ static int produced;
+
+ PT_BEGIN(pt);
+
+ for(produced = 0; produced < NUM_ITEMS; ++produced) {
+
+ PT_SEM_WAIT(pt, &full);
+
+ PT_SEM_WAIT(pt, &mutex);
+ add_to_buffer(produce_item());
+ PT_SEM_SIGNAL(pt, &mutex);
+
+ PT_SEM_SIGNAL(pt, &empty);
+ }
+
+ PT_END(pt);
+}
+
+PT_THREAD(consumer(struct pt *pt))
+{
+ static int consumed;
+
+ PT_BEGIN(pt);
+
+ for(consumed = 0; consumed < NUM_ITEMS; ++consumed) {
+
+ PT_SEM_WAIT(pt, &empty);
+
+ PT_SEM_WAIT(pt, &mutex);
+ consume_item(get_from_buffer());
+ PT_SEM_SIGNAL(pt, &mutex);
+
+ PT_SEM_SIGNAL(pt, &full);
+ }
+
+ PT_END(pt);
+}
+
+PT_THREAD(driver_thread(struct pt *pt))
+{
+ static struct pt pt_producer, pt_consumer;
+
+ PT_BEGIN(pt);
+
+ PT_SEM_INIT(&empty, 0);
+ PT_SEM_INIT(&full, BUFSIZE);
+ PT_SEM_INIT(&mutex, 1);
+
+ PT_INIT(&pt_producer);
+ PT_INIT(&pt_consumer);
+
+ PT_WAIT_THREAD(pt, producer(&pt_producer) &
+ consumer(&pt_consumer));
+
+ PT_END(pt);
+}
+ \endcode
+ *
+ * The program uses three protothreads: one protothread that
+ * implements the consumer, one thread that implements the producer,
+ * and one protothread that drives the two other protothreads. The
+ * program uses three semaphores: "full", "empty" and "mutex". The
+ * "mutex" semaphore is used to provide mutual exclusion for the
+ * buffer, the "empty" semaphore is used to block the consumer is the
+ * buffer is empty, and the "full" semaphore is used to block the
+ * producer is the buffer is full.
+ *
+ * The "driver_thread" holds two protothread state variables,
+ * "pt_producer" and "pt_consumer". It is important to note that both
+ * these variables are declared as <i>static</i>. If the static
+ * keyword is not used, both variables are stored on the stack. Since
+ * protothreads do not store the stack, these variables may be
+ * overwritten during a protothread wait operation. Similarly, both
+ * the "consumer" and "producer" protothreads declare their local
+ * variables as static, to avoid them being stored on the stack.
+ *
+ *
+ */
+
+/**
+ * \file
+ * Couting semaphores implemented on protothreads
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PT_SEM_H__
+#define __PT_SEM_H__
+
+#include "pt.h"
+
+struct pt_sem {
+ unsigned int count;
+};
+
+/**
+ * Initialize a semaphore
+ *
+ * This macro initializes a semaphore with a value for the
+ * counter. Internally, the semaphores use an "unsigned int" to
+ * represent the counter, and therefore the "count" argument should be
+ * within range of an unsigned int.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \param c (unsigned int) The initial count of the semaphore.
+ * \hideinitializer
+ */
+#define PT_SEM_INIT(s, c) (s)->count = c
+
+/**
+ * Wait for a semaphore
+ *
+ * This macro carries out the "wait" operation on the semaphore. The
+ * wait operation causes the protothread to block while the counter is
+ * zero. When the counter reaches a value larger than zero, the
+ * protothread will continue.
+ *
+ * \param pt (struct pt *) A pointer to the protothread (struct pt) in
+ * which the operation is executed.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \hideinitializer
+ */
+#define PT_SEM_WAIT(pt, s) \
+ do { \
+ PT_WAIT_UNTIL(pt, (s)->count > 0); \
+ --(s)->count; \
+ } while(0)
+
+/**
+ * Signal a semaphore
+ *
+ * This macro carries out the "signal" operation on the semaphore. The
+ * signal operation increments the counter inside the semaphore, which
+ * eventually will cause waiting protothreads to continue executing.
+ *
+ * \param pt (struct pt *) A pointer to the protothread (struct pt) in
+ * which the operation is executed.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \hideinitializer
+ */
+#define PT_SEM_SIGNAL(pt, s) ++(s)->count
+
+#endif /* __PT_SEM_H__ */
+
+/** @} */
+/** @} */
+
--- /dev/null
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: pt.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \file
+ * Protothreads implementation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PT_H__
+#define __PT_H__
+
+#include "lc.h"
+
+typedef struct _pt {
+ lc_t lc;
+} pt;
+
+#define PT_WAITING 0
+#define PT_YIELDED 1
+#define PT_EXITED 2
+#define PT_ENDED 3
+
+/**
+ * \name Initialization
+ * @{
+ */
+
+/**
+ * Initialize a protothread.
+ *
+ * Initializes a protothread. Initialization must be done prior to
+ * starting to execute the protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_INIT(pt) LC_INIT((pt)->lc)
+
+/** @} */
+
+/**
+ * \name Declaration and definition
+ * @{
+ */
+
+/**
+ * Declaration of a protothread.
+ *
+ * This macro is used to declare a protothread. All protothreads must
+ * be declared with this macro.
+ *
+ * \param name_args The name and arguments of the C function
+ * implementing the protothread.
+ *
+ * \hideinitializer
+ */
+#define PT_THREAD(name_args) char name_args
+
+/**
+ * Declare the start of a protothread inside the C function
+ * implementing the protothread.
+ *
+ * This macro is used to declare the starting point of a
+ * protothread. It should be placed at the start of the function in
+ * which the protothread runs. All C statements above the PT_BEGIN()
+ * invokation will be executed each time the protothread is scheduled.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
+
+/**
+ * Declare the end of a protothread.
+ *
+ * This macro is used for declaring that a protothread ends. It must
+ * always be used together with a matching PT_BEGIN() macro.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
+ PT_INIT(pt); return PT_ENDED; }
+
+/** @} */
+
+/**
+ * \name Blocked wait
+ * @{
+ */
+
+/**
+ * Block and wait until condition is true.
+ *
+ * This macro blocks the protothread until the specified condition is
+ * true.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param condition The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_UNTIL(pt, condition) \
+ do {/*printf("Test1: %d, %s\n",__LINE__,__FILE__);*/ \
+ LC_SET((pt)->lc); /*printf("Test2: %d\n",(pt)->lc);*/ \
+ if(!(condition)) { \
+ return PT_WAITING; \
+ } \
+ } while(0)
+
+/**
+ * Block and wait while condition is true.
+ *
+ * This function blocks and waits while condition is true. See
+ * PT_WAIT_UNTIL().
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
+
+/** @} */
+
+/**
+ * \name Hierarchical protothreads
+ * @{
+ */
+
+/**
+ * Block and wait until a child protothread completes.
+ *
+ * This macro schedules a child protothread. The current protothread
+ * will block until the child protothread completes.
+ *
+ * \note The child protothread must be manually initialized with the
+ * PT_INIT() function before this function is used.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
+
+/**
+ * Spawn a child protothread and wait until it exits.
+ *
+ * This macro spawns a child protothread and waits until it exits. The
+ * macro can only be used within a protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param child A pointer to the child protothread's control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \hideinitializer
+ */
+#define PT_SPAWN(pt, child, thread) \
+ do { \
+ PT_INIT((child)); \
+ PT_WAIT_THREAD((pt), (thread)); \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Exiting and restarting
+ * @{
+ */
+
+/**
+ * Restart the protothread.
+ *
+ * This macro will block and cause the running protothread to restart
+ * its execution at the place of the PT_BEGIN() call.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_RESTART(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_WAITING; \
+ } while(0)
+
+/**
+ * Exit the protothread.
+ *
+ * This macro causes the protothread to exit. If the protothread was
+ * spawned by another protothread, the parent protothread will become
+ * unblocked and can continue to run.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_EXIT(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_EXITED; \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Calling a protothread
+ * @{
+ */
+
+/**
+ * Schedule a protothread.
+ *
+ * This function shedules a protothread. The return value of the
+ * function is non-zero if the protothread is running or zero if the
+ * protothread has exited.
+ *
+ * \param f The call to the C function implementing the protothread to
+ * be scheduled
+ *
+ * \hideinitializer
+ */
+#define PT_SCHEDULE(f) ((f) < PT_EXITED)
+
+/** @} */
+
+/**
+ * \name Yielding from a protothread
+ * @{
+ */
+
+/**
+ * Yield from the current protothread.
+ *
+ * This function will yield the protothread, thereby allowing other
+ * processing to take place in the system.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD(pt) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if(PT_YIELD_FLAG == 0) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/**
+ * \brief Yield from the protothread until a condition occurs.
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * This function will yield the protothread, until the
+ * specified condition evaluates to true.
+ *
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD_UNTIL(pt, cond) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if((PT_YIELD_FLAG == 0) || !(cond)) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/** @} */
+
+#endif /* __PT_H__ */
+
+/** @} */
--- /dev/null
+/*
+ * FastCommunication.cpp
+ *
+ * Created on: Mar 3, 2009
+ * Author: lschor
+ *
+ * Provides the communication between various processors.
+ *
+ *
+ *
+ * Description:
+ *
+ * Sender: The processor now has some data that need to be forwarded
+ * to another processor.
+ * Receiver: The processor that needs to get the data.
+ *
+ * Sender ---- *
+ * -----> Have some data *
+ * (Len, queue) *
+ * -----------> Receiver *
+ * *
+ * Check its len *
+ * *
+ * Sets up a DMA *
+ * transfer to *
+ * read from the *
+ * <-------------- queue to a *
+ * MFC performs the local buffer *
+ * transfer (Alignment) *
+ * <--------- *
+ * *
+ * *
+ * (Pools if the *
+ * transfer is *
+ * completed) *
+ * *
+ * *
+ * Copy the data *
+ * from its temp. *
+ * buffer to the *
+ * queue und *
+ * Have completed <------------ informs the *
+ * <---------- (queue, len) sender *
+ * Can increase the *
+ * pointers in the FIFO
+ *
+ *
+ * Has two ways to handling request, which are not possible
+ * to work out currently:
+ * 1) Send back "len = 0"
+ * --> Needs to send more messages, but may bigger lens
+ * 2) Store them until you have enough space to read
+ * --> Smaller lens and less messages
+ */
+
+#include "FastCommunication.h"
+
+/*
+ * Constructor
+ */
+FastCommunication::FastCommunication(int nrOfQueues, uint64_t ea_base,
+ uint64_t *ea_base_all, int32_t * queueFromSPEIn,
+ int32_t * queueOnSPEIn, uint64_t *fifoTails) {
+
+ // Set the base address
+ _ea_base = ea_base;
+
+ _ea_base_all = ea_base_all;
+ queueFromSPE = queueFromSPEIn;
+ queueOnSPE = queueOnSPEIn;
+ _fifoTails = fifoTails;
+
+ _nrOfQueues = nrOfQueues;
+ try { _fifos = new fifoCollection[nrOfQueues]; }
+ catch(std::bad_alloc &e) {
+ fprintf(stderr, "[FastCommunication] Memory allocation failure\n");
+ exit(1);
+ }
+ _nrOfRequest = 0;
+
+ for (int i = 0; i < MAXNOREQ; i++) {
+ _request[i].valid = false;
+ }
+}
+
+/*
+ * Deconstructor
+ */
+FastCommunication::~FastCommunication() {
+ delete _fifos;
+}
+
+/*
+ * Register an additional FIFO in the Communication
+ */
+bool FastCommunication::addFifo(int fifoNr, Fifo* fifo, int type,
+ int queue) {
+ _fifos[fifoNr].fifo = fifo;
+ _fifos[fifoNr].queue = queue;
+ _fifos[fifoNr].type = type;
+ _fifos[fifoNr].iswfifo = false;
+
+ // Per FIFO queue, we need two requests, but we store at max MAXNOREQ of them
+ if (_nrOfRequest < MAXNOREQ) {
+ _nrOfRequest += 2;
+ }
+
+ return true;
+}
+
+/*
+ * Register an additional WindowedFIFO in the Communication
+ */
+bool FastCommunication::addWFifo(int fifoNr, WindowedFifo* wfifo,
+ int type, int queue) {
+ _fifos[fifoNr].wfifo = wfifo;
+ _fifos[fifoNr].queue = queue;
+ _fifos[fifoNr].type = type;
+ _fifos[fifoNr].iswfifo = true;
+
+ // Per FIFO queue, we need two requests, but we store at max MAXNOREQ of them
+ if (_nrOfRequest < MAXNOREQ) {
+ _nrOfRequest += 2;
+ }
+
+ return true;
+}
+
+/*
+ * Communication: Main update procedure to update
+ */
+bool FastCommunication::update() {
+ // Check if you have received a new message
+ while (spu_stat_in_mbox() > 0) {
+ uint32_t messageIn = spu_read_in_mbox();
+
+ uint32_t code = GETFASTCODE(messageIn);
+ uint32_t queue = GETFASTQUEUE(messageIn);
+ uint32_t len = GETFASTLEN(messageIn);
+
+ /***************************************************************************************************************/
+ if (code == SPE_READ_DEMAND) // One should start a read process
+ {
+ // Find out for which fifo the request is
+ fifoCollection *fifocol = NULL;
+ int i = 0;
+ for (i = 0; i < _nrOfQueues; i++) {
+ if (_fifos[i].queue == queue) {
+ fifocol = &_fifos[i];
+ break;
+ }
+ }
+
+ // The queue was not found
+ if (fifocol == NULL) {
+ printf("SPU COM> ERROR, this queue does not exists!\n");
+ return false;
+ }
+
+ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // Windowed FIFO
+ if (_fifos[i].iswfifo) {
+
+ WindowedFifo* wfifo = NULL;
+ wfifo = _fifos[i].wfifo;
+
+ // Find the current tail of the queue from where to read
+ uint32_t inTail = wfifo->_inTail;
+
+ // This is the len we like to read
+ len = len > (wfifo->unused()) ? wfifo->unused() : len;
+
+ // We can read something
+ if (len > 0) {
+ // Write all information we used to the request-memory
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ // not possible to start a request for this SPE --> Send len = 0
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+ return false;
+ }
+
+ // reserve DMA tag ID
+ uint32_t tag_id;
+ if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID) {
+ printf("SPE: ERROR - can't reserve a tag ID\n");
+ return false;
+ }
+
+ // Generate the base address of the input FIFO
+ uint64_t baseAddress = _fifoTails[queue] + inTail;
+
+ // Align the address to the correct factor (in general 128 or 32)
+ while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
+ baseAddress--;
+
+ // Offset --> How much we had to align
+ uint32_t offset = _fifoTails[queue] + inTail
+ - baseAddress;
+
+ request->data = (char *) _malloc_align(roundDMA(len
+ + offset), ALIGNMENT_FACTOR);
+
+ // Store all data in the request buffer
+ request->len = len;
+
+ request->wfifo = wfifo;
+ request->iswfifo = true;
+
+ request->status = read_started;
+ request->queue = queue;
+ request->offset = offset;
+ request->tag_id = tag_id;
+
+ // Set up the request in the MFC
+ mfc_get((void *) &(request->data[0]), baseAddress,
+ roundDMA(len + offset), tag_id, 0, 0);
+ }
+
+ else {
+#ifndef STORE_REQUESTS // Send len = 0 back to the sender, this one should try it in a later phase
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+#else // I store the request and may try in a later time to start the transfer
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL)
+ {
+ // not possible to start a request for this SPE --> Send len = 0
+ uint32_t message = CREATEFASTMESSAGE(SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+ return false;
+ }
+
+ request->len = len;
+ request->wfifo = wfifo;
+ request->iswfifo = true;
+ request->status = read_pending;
+ request->queue = queue;
+#endif
+ }
+ }
+
+ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // Classic FIFO
+ else {
+ Fifo* fifo = NULL;
+ fifo = _fifos[i].fifo;
+
+ uint32_t inTail = fifo->_inTail;
+
+ // This is the len we like to read
+ len = len > (fifo->unused()) ? fifo->unused() : len;
+
+ // We can read something
+ if (len > 0) {
+ // Write all information we used to the request-memory
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ // not possible to start a request for this SPE --> Send len = 0
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+ return false;
+ }
+
+ uint32_t tag_id;
+
+ // reserve DMA tag ID
+ if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID) {
+ printf("SPE: ERROR - can't reserve a tag ID\n");
+ return false;
+ }
+
+ uint64_t baseAddress = _fifoTails[queue] + inTail;
+
+ while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
+ baseAddress--;
+
+ // Offset
+ uint32_t offset = _fifoTails[queue] + inTail
+ - baseAddress;
+
+ // Store all data in the request buffer
+ request->data = (char *) _malloc_align(roundDMA(len
+ + offset), ALIGNMENT_FACTOR);
+ request->len = len;
+ request->fifo = fifo;
+ request->iswfifo = false;
+ request->status = read_started;
+ request->queue = queue;
+ request->offset = offset;
+ request->tag_id = tag_id;
+
+ // Tell the fifo that one has reserved some data
+
+ mfc_get((void *) &(request->data[0]), baseAddress,
+ roundDMA(len + offset), tag_id, 0, 0);
+ }
+
+ // len == 0
+ else {
+#ifndef STORE_REQUESTS // Send len = 0 back to the sender, this one should try it in a later phase
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+#else // I store the request and may try in a later time to start the transfer
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL)
+ {
+ // not possible to start a request for this SPE --> Send len = 0
+ uint32_t message = CREATEFASTMESSAGE(SPE_READ_COMPLETE, queue, 0);
+ sendMessage(message, queueFromSPE[queue]);
+ return false;
+ }
+
+ request->len = len;
+ request->fifo = fifo;
+ request->iswfifo = false;
+ request->status = read_pending;
+ request->queue = queue;
+#endif
+ }
+ }
+ }
+
+ /***************************************************************************************************************/
+ else if (code == SPE_READ_COMPLETE) // A read has finished
+ {
+ // Get the stored request
+ comRequest* request = getRequest(read_request_sent, queue);
+ if (request == NULL) {
+ printf(
+ ">>>>>>>>>>>>>>>>> Communicate SPU> Couldn't find the request\n");
+ return 0;
+ }
+
+ // Inform my FIFO that the request is completed
+ if (request->iswfifo)
+ request->wfifo->dmaRead(len);
+ else
+ request->fifo->dmaRead(len);
+
+ // Request free
+ deleteRequest(request);
+ }
+ }
+
+ /***************************************************************************************************************/
+ // Check if some active write processes have finished
+ uint8_t req = _currentRequest;
+
+ for (int i = 0; i < _nrOfRequest; i++) // Check all possible requests
+ {
+ if (_request[req].valid) // Only to check if the request is valid
+ {
+ if (_request[req].status == read_started) { // We have setup the request, now check if it is complete
+
+ // If I cannot send a message to the corresponding processor --> Do not have to check it
+ if (!(testMessage(queueOnSPE[_request[req].queue]) > 0))
+ continue;
+
+ // Check if the specific Tag-ID has completed
+ uint32_t tag_id = _request[req].tag_id;
+ mfc_write_tag_mask(1 << tag_id);
+ mfc_write_tag_update(MFC_TAG_UPDATE_IMMEDIATE);
+ uint32_t ret = mfc_read_tag_status();
+
+ if (!((ret & (1 << tag_id)) == 0)) {
+
+ // This update is finished
+ mfc_tag_release(tag_id);
+
+ // Have to write the data into the fifo
+ if (_request[req].iswfifo) { // WFIFO
+
+ _request[req].wfifo->dmaWrite(
+ (char *) _request[req].data
+ + _request[req].offset,
+ _request[req].len);
+ _free_align(_request[req].data);
+
+ // Increase the inTail value (used to know where the last request was started)
+ _request[req].wfifo->_inTail
+ = (_request[req].wfifo->_inTail
+ + _request[req].len) % (FIFO_SIZE[_request[req].queue]);
+ } else { // FIFO
+ _request[req].fifo->write(
+ (char *) _request[req].data
+ + _request[req].offset,
+ _request[req].len);
+ _free_align(_request[req].data);
+
+ _request[req].fifo->_inTail
+ = (_request[req].fifo->_inTail
+ + _request[req].len) % (FIFO_SIZE[_request[req].queue]);
+
+ }
+
+ // Inform the sender about the event
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_COMPLETE, _request[req].queue,
+ _request[req].len);
+ sendMessage(message, queueFromSPE[_request[req].queue]);
+
+ // Delete the request
+ deleteRequest(&_request[req]);
+ _currentRequest = (req + 1) % _nrOfRequest;
+
+ break; // continue is also working
+ }
+ } else if (_request[req].status == read_pending) { // Has an open request for sending
+
+ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // Windowed FIFO
+ if (_request[req].iswfifo) {
+
+ if (_request[req].wfifo->unused() > 0) {
+ comRequest *request = &_request[req];
+
+ // This is the len we like to read
+ uint32_t len = request->len > (request->wfifo->unused()) ? request->wfifo->unused()
+ : request->len;
+
+ // reserve DMA tag ID
+ uint32_t tag_id;
+ if ((tag_id = mfc_tag_reserve())
+ == MFC_TAG_INVALID) {
+ printf("SPE: ERROR - can't reserve a tag ID\n");
+ return false;
+ }
+
+ uint32_t inTail = request->wfifo->_inTail;
+ uint64_t baseAddress = _fifoTails[request->queue]
+ + inTail;
+
+ while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
+ baseAddress--;
+
+ // Offset --> How much we had to align
+ uint32_t offset = _fifoTails[request->queue]
+ + inTail - baseAddress;
+
+ request->data = (char *) _malloc_align(roundDMA(
+ len + offset), ALIGNMENT_FACTOR);
+ request->len = len;
+ request->status = read_started;
+ request->offset = offset;
+ request->tag_id = tag_id;
+
+ // Set up the request in the MFC
+ mfc_get((void *) &(request->data[0]), baseAddress,
+ roundDMA(len + offset), tag_id, 0, 0);
+ }
+ }
+
+ // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // Classic FIFO
+ else {
+
+ if (_request[req].fifo->unused() > 0) {
+ comRequest *request = &_request[req];
+
+ // This is the len we like to read
+ uint32_t len = request->len > (request->fifo->unused()) ? request->fifo->unused()
+ : request->len;
+
+ uint32_t tag_id;
+ // reserve DMA tag ID
+ if ((tag_id = mfc_tag_reserve())
+ == MFC_TAG_INVALID) {
+ printf("SPE: ERROR - can't reserve a tag ID\n");
+ return false;
+ }
+
+ uint32_t inTail = request->fifo->_inTail;
+ uint64_t baseAddress = _fifoTails[request->queue] + inTail;
+
+ while (baseAddress % ALIGNMENT_FACTOR_POWER2 != 0)
+ baseAddress--;
+
+ // Offset
+ uint32_t offset = _fifoTails[request->queue]
+ + inTail - baseAddress;
+
+ // Store all data in the request buffer
+ request->data = (char *) _malloc_align(roundDMA(
+ len + offset), ALIGNMENT_FACTOR);
+ request->len = len;
+ request->status = read_started;
+ request->offset = offset;
+ request->tag_id = tag_id;
+
+ // Start the DMA transfer
+ mfc_get((void *) &(request->data[0]), baseAddress,
+ roundDMA(len + offset), tag_id, 0, 0);
+ }
+ }
+ }
+ }
+ // Go to the next Request
+ req = (req + 1) % _nrOfRequest;
+ }
+
+ /***************************************************************************************************************/
+ // Start a new request to the receiver of a FIFO
+ for (int i = 0; i < _nrOfQueues; i++) {
+ if (_fifos[i].type == this->out) // Only out-FIFO have to be quecked
+ {
+ if (_fifos[i].iswfifo) { // WFIFO
+
+ // Start only a write process if there is really enough place in the outbound mailbox
+ if (_fifos[i].wfifo->dmaAllowed() && _fifos[i].wfifo->used() > 0) {
+ uint32_t queue = _fifos[i].queue;
+
+ // Can we send a message to this processor or is it blocked?
+ if (testMessage(queueOnSPE[queue]) <= 0) {
+ continue;
+ }
+
+ // Write all information we used to the request-memory
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ } else {
+ uint32_t len = _fifos[i].wfifo->dmaStart();
+ // Create a write-demand message
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_DEMAND, queue, len);
+
+ request->len = len;
+ request->queue = queue;
+ request->status = read_request_sent;
+ request->wfifo = _fifos[i].wfifo;
+ request->iswfifo = true;
+
+ sendMessage(message, queueOnSPE[queue]);
+ }
+ break;
+ }
+ } else { // FIFO
+
+ // Start only a write process if there is really enough place in the outbound mailbox
+ if (_fifos[i].fifo->dmaAllowed() && _fifos[i].fifo->used() > 0) {
+ uint32_t queue = _fifos[i].queue;
+
+ // Check if we can send a message to the processor
+ if (testMessage(queueOnSPE[queue]) <= 0) {
+ continue;
+ }
+
+ // Write all information we used to the request-memory
+ comRequest* request = newRequest();
+
+ // Has no memory to store a new request
+ if (request == NULL) {
+ } else {
+ uint32_t len = _fifos[i].fifo->dmaStart();
+ // Create a write-demand message
+ uint32_t message = CREATEFASTMESSAGE(
+ SPE_READ_DEMAND, queue, len);
+
+ request->len = len;
+ request->queue = queue;
+ request->status = read_request_sent;
+ request->fifo = _fifos[i].fifo;
+ request->iswfifo = false;
+
+ sendMessage(message, queueOnSPE[queue]);
+ }
+ break;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+/*
+ * Create a new request to store in the cache
+ *
+ */
+comRequest* FastCommunication::newRequest() {
+ for (int i = 0; i < _nrOfRequest; i++) {
+ if (!_request[i].valid) {
+ _request[i].valid = true;
+ return &(_request[i]);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Delete the request
+ *
+ */
+void FastCommunication::deleteRequest(comRequest* request) {
+ request->valid = false;
+}
+
+/*
+ * Returns the request one like to get
+ */
+comRequest* FastCommunication::getRequest(uint8_t status, uint32_t queue) {
+ uint8_t req = _currentRequest;
+
+ for (int i = 0; i < _nrOfRequest; i++) {
+ if (_request[req].valid && _request[req].status == status
+ && _request[req].queue == queue) {
+ _currentRequest = (req + 1) % _nrOfRequest;
+ return &(_request[req]);
+ }
+ req = (req + 1) % _nrOfRequest;
+ }
+
+ return NULL;
+}
+
+/**
+ * True if no communication is necessary, false if there is active communication
+ */
+bool FastCommunication::empty() {
+ // check if one fifo would like to send something to another SPE
+ for (int i = 0; i < _nrOfQueues; i++) {
+ if (_fifos[i].type == this->out) {
+ if (_fifos[i].iswfifo) {
+ if (_fifos[i].wfifo->used() > 0)
+ {
+ return false;
+ }
+ } else {
+ if (_fifos[i].fifo->used() > 0)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ // are open sendings?
+ for (int i = 0; i < _nrOfRequest; i++) {
+ if (_request[i].valid) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void FastCommunication::sendMessage(uint32_t message, int32_t process) {
+ // Simple forward the message to the PPE
+ if (process <= -1) {
+ spu_write_out_mbox(message);
+ }
+
+ // Forward message to the corresponding SPE
+ else {
+ uint32_t tag_id;
+
+ // reserve DMA tag ID
+ if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID) {
+ printf("SPE: ERROR - can't reserve a tag ID\n");
+ return;
+ }
+
+ //printf("SPE > OUT Message to process = %d, addr = %llx\n", process, _ea_base_all[process]);
+ write_in_mbox(message, _ea_base_all[process], tag_id);
+ mfc_tag_release(tag_id);
+ }
+}
+
+int FastCommunication::testMessage(int32_t process) {
+ //int32_t process = queueOnSPE[queue];
+
+ // Simple forward the message to the PPE
+ if (process <= -1) {
+ return spu_stat_out_mbox();
+ }
+
+ // Forward message to the corresponding SPE
+ else {
+ uint32_t tag_id;
+
+ // reserve DMA tag ID
+ if ((tag_id = mfc_tag_reserve()) == MFC_TAG_INVALID) {
+ printf("SPE: ERROR - can't reserve a tag ID\n");
+ return 0;
+ }
+
+ // IMPORTANT: THIS IS NOT RACE CONDITION FREE!!!!
+ int test = status_in_mbox(_ea_base_all[process], tag_id);
+ mfc_tag_release(tag_id);
+ return test;
+ }
+}
--- /dev/null
+/*
+ * FastCommunication.h
+ *
+ * Created on: Mar 3, 2009
+ * Author: lschor
+ */
+
+#ifndef FASTCOMMUNICATION_H_
+#define FASTCOMMUNICATION_H_
+
+// CBE includes
+#include <spu_intrinsics.h>
+#include <spu_mfcio.h>
+
+// C++ includes
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+
+// Local includes
+#include "Fifo.h"
+#include "WindowedFifo.h"
+#include "../common.h"
+
+// For external Mailbox Communication
+#include "../spu_mfcio_ext.h"
+
+// Include to allocate/free using for DMA transfers
+#include "../lib/malloc_align.h"
+#include "../lib/free_align.h"
+
+//Cell Macros
+#define waittag(tag_id) mfc_write_tag_mask(1<<tag_id); mfc_read_tag_status_all();
+
+#define MAXNOREQ 256
+
+// This is a full Request
+typedef struct _comRequest {
+ bool valid; // If the request is valid
+ uint32_t status; // Status of the request (read_..., ...)
+
+ uint32_t tag_id; // Tag ID
+ uint32_t queue; // The queue which is used by the request
+
+ bool iswfifo; // True if it is a WFIFO
+ Fifo* fifo; // Pointer to the used FIFO
+ WindowedFifo* wfifo; // Pointer to the WFIFO
+
+ uint32_t len; // The len of the data
+ char* data; // Point to the data which are stored
+ uint32_t offset; // Offset generated by alignment
+} comRequest;
+
+// Struct to store a FIFO
+typedef struct _fifoCollection {
+ int type; // local, in or out
+ int queue; // Corresponding queue number
+
+ bool iswfifo; // True if it is a WFIFO
+ WindowedFifo* wfifo; // Pointer to the WFIFO
+ Fifo* fifo; // Pointer to the FIFO
+} fifoCollection;
+
+/**
+ * The Communication Class
+ */
+class FastCommunication {
+public:
+ FastCommunication(int nrOfQueues, uint64_t ea_base, uint64_t *ea_base_all, int32_t * queueFromSPE, int32_t * queueOnSPE, uint64_t * fifoTails);
+ virtual ~FastCommunication();
+
+ bool addFifo(int fifoNr, Fifo* fifo, int type, int queue);
+ bool addWFifo(int fifoNr, WindowedFifo* fifo, int type, int queue);
+
+ bool update();
+ bool empty();
+
+ static int const local = 0;
+ static int const in = 1;
+ static int const out = 2;
+
+ static int const comIn = 0;
+ static int const comOut = 1;
+
+ static int const read_request_sent = 0;
+ static int const read_started = 1;
+ static int const read_pending = 2;
+
+protected:
+ // To send messages
+ void sendMessage(uint32_t message, int32_t process);
+ int testMessage(int32_t process);
+
+ // Requests
+ comRequest* newRequest();
+ void deleteRequest(comRequest* request);
+ comRequest* getRequest(uint8_t status, uint32_t queue);
+
+ // Queues
+ int _nrOfQueues;
+ fifoCollection * _fifos;
+
+ // Request
+ int _nrOfRequest; // Need only 2 requests per queue (others are blocked...)
+ comRequest _request[MAXNOREQ]; // Stores at maximum 12 requests
+ uint8_t _currentRequest; // The current request (so that we can start in the next iteration by the next one)
+
+ // Pointers for communication
+ uint64_t _ea_base; // This is my base address
+ uint64_t * _ea_base_all; // All base addresses of the control blocks of the other SPEs (for sending message to)
+ int32_t * queueFromSPE; // Array which tells us from which processor a queue comes
+ int32_t * queueOnSPE; // Array which tells us to which processor a queue goes
+ uint64_t * _fifoTails; // Pointers to the tail of the other queues
+};
+
+#endif /* FASTCOMMUNICATION_H_ */
--- /dev/null
+#include "Fifo.h"
+
+/**
+ *
+ */
+Fifo::Fifo(unsigned size = 18) {
+ //except at the beginning, _head and _tail must never overlap,
+ //otherwise one does not know whether the buffer is full or
+ //empty. to have nevertheless a buffer with the given capacity,
+ //a buffer with one more element is allocated.
+
+ _size = size;
+ _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR);
+ if(!_buffer) {
+ fprintf(stderr,"[FIFO] Memory allocation failure\n");
+ exit(-1);
+ }
+ _pos = 0;
+ _tail = 0;
+ _blocked = 0;
+
+ _inTail = 0;
+ _activeDMA = false;
+}
+
+/**
+ *
+ */
+Fifo::~Fifo() {
+ if (_buffer) {
+ _free_align(_buffer);
+ }
+ _buffer = 0;
+ _pos = 0;
+ _tail = 0;
+}
+
+/**
+ *
+ */
+unsigned Fifo::read(void *destination, unsigned len) {
+
+ char* buffer = (char*) destination;
+ unsigned read = (len <= used() ? len : used());
+
+ if (_tail + read < _size) {
+ memcpy(buffer, _buffer + _tail, read);
+ } else {
+ memcpy(buffer, _buffer + _tail, _size - _tail);
+ memcpy(buffer + _size - _tail, _buffer, read - _size + _tail);
+ }
+
+ _tail = ((unsigned) (_tail + read) % _size);
+ _pos -= read;
+ return read;
+}
+
+/**
+ *
+ */
+unsigned Fifo::write(const void *source, unsigned len) {
+
+ char* buffer = (char*) source;
+ unsigned write = (len <= unused() ? len : unused());
+ unsigned head = (_tail + _pos) % _size;
+
+ if (head + write < _size) {
+ memcpy(_buffer + head, buffer, write);
+ } else {
+ memcpy(_buffer + head, buffer, _size - head);
+ memcpy(_buffer, buffer + _size - head, write - _size + head);
+ }
+
+ _pos += write;
+ return write;
+}
+
+/**
+ * Size of this fifo
+ */
+unsigned Fifo::size() const {
+ return (_size);
+}
+
+/**
+ * How many bytes is currently free in the buffer
+ */
+unsigned Fifo::unused() const {
+ return (_size) - used();
+}
+
+/**
+ * How many data are currently stored in the fifo
+ */
+unsigned Fifo::used() const {
+ return _pos;
+}
+
+/*
+ * Get the pointer to the start of the queue
+ */
+char *Fifo::getQueuePointer() {
+ return _buffer;
+}
+
+/*
+ * Has completed a dma read process, i.e. has read out of the queue
+ */
+void Fifo::dmaRead(unsigned len) {
+ _activeDMA = false;
+
+ if (len == 0) {
+ _blocked = BLOCKED_MAX_NR;
+ } else {
+ _tail = ((unsigned) (_tail + len) % _size);
+ _pos -= len;
+ }
+}
+
+/*
+ * Start a DMA request, returns the current space one have
+ */
+unsigned Fifo::dmaStart() {
+ _activeDMA = true;
+
+ if (_tail + _pos > _size) {
+ return _size - _tail;
+ } else {
+ return _pos;
+ }
+}
+
+/*
+ * Is allowed to start a dma request
+ */
+bool Fifo::dmaAllowed() {
+ if (_blocked > 0) {
+ _blocked--;
+ return false;
+ } else {
+ return !_activeDMA;
+ }
+}
+
+/**
+ * Test the implementation
+ */
+/*
+ int main() {
+ std::cout.width(5);
+ Fifo *myFifo = new Fifo();
+ for (int j = 0; j < 3; j++) {
+ for (int i = 0; i < 6; i++) {
+ std::cout << "write " << i << " to Fifo. ";
+ int write = myFifo->write(&i, sizeof(int));
+ printf(" %d ", write);
+ if (write == sizeof(int)) {
+ std::cout << "used: " << std::setw(2) << myFifo->used()
+ << ", unused: " << std::setw(2) << myFifo->unused()
+ << ", size: " << std::setw(2) << myFifo->size()
+ << std::endl;
+ } else {
+ std::cout << std::endl;
+ }
+ }
+ for (int i = 0; i < 6; i++) {
+ int value;
+ int read = myFifo->read(&value, sizeof(int));
+ printf(" %d ", read);
+ if (read == sizeof(int)) {
+ std::cout << "read " << value << " from Fifo ";
+ std::cout << "used: " << std::setw(2) << myFifo->used()
+ << ", unused: " << std::setw(2) << myFifo->unused()
+ << ", size: " << std::setw(2) << myFifo->size()
+ << std::endl;
+ }
+ }
+ }
+ delete myFifo;
+ return 0;
+ }
+ */
--- /dev/null
+#ifndef _FIFO_H_
+#define _FIFO_H_
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../constant.h"
+
+#include "../lib/malloc_align.h"
+#include "../lib/free_align.h"
+
+class Fifo {
+ public:
+ Fifo(unsigned size);
+ virtual ~Fifo();
+
+ // Read / Write
+ virtual unsigned read(void *destination, unsigned len);
+ virtual unsigned write(const void *source, unsigned len);
+
+ // Buffer functions
+ virtual unsigned used() const;
+ virtual unsigned unused() const;
+ virtual unsigned size() const;
+
+ // DMA functions
+ virtual char *getQueuePointer();
+ virtual void dmaRead(unsigned len);
+ virtual unsigned dmaStart();
+ virtual bool dmaAllowed();
+
+ // Global Variables
+ unsigned _inTail;
+
+ protected:
+ char *_buffer; // Buffer pointer
+
+ unsigned _tail; // Pointer to the tail
+
+ unsigned _pos; // Amount used
+ unsigned _size; // Size of the buffer
+
+ unsigned _blocked; // Number of blocking necessary
+ bool _activeDMA; // Active DMA?
+};
+
+#endif
--- /dev/null
+#include "WindowedFifo.h"
+
+/**
+ *
+ */
+WindowedFifo::WindowedFifo(unsigned size = 20) {
+ //std::cout << "Create WindowedFifo." << std::endl;
+
+ _size = size;
+ _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR);
+ if(!_buffer) {
+ fprintf(stderr,"[WFIFO] Memory allocation failure\n");
+ exit(-1);
+ }
+ _head = 0;
+ _tail = 0;
+ _headRoom = 0;
+ _tailRoom = 0;
+ _use = 0;
+
+ _isHeadReserved = false;
+ _isTailReserved = false;
+
+ // For DMA transfers
+ _blocked = 0;
+ _activeDMA = false;
+}
+
+/**
+ *
+ */
+WindowedFifo::~WindowedFifo() {
+ //std::cout << "Delete WindowedFifo." << std::endl;
+ if (_buffer) {
+ _free_align(_buffer);
+ }
+ _buffer = 0;
+ _head = 0;
+ _tail = 0;
+ _use = 0;
+ //std::cout << "Deleted WindowedFifo." << std::endl;
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::reserve(char** destination, unsigned len) {
+
+ //std::cout << "Attempt to reserve " << len << " bytes." << std::endl;
+
+ //can only reserve once piece at a time
+ if (_isHeadReserved) {
+ *destination = 0;
+ return 0;
+ }
+
+ //reserve at most as much memory as still available in the buffer
+ unsigned write = (len <= _size - _use ? len : 0);
+
+ if (write > 0) {
+ //if wrap-around in buffer: return only buffer for the
+ //contiguous buffer space
+ if (_head + write > _size) {
+ write = _size - _head;
+ }
+
+ _headRoom = (_head + write) == _size ? 0 : _head + write;
+ *destination = &(_buffer[_head]);
+ _isHeadReserved = true;
+ }
+
+ //std::cout << "Reserved " << write << " bytes." << std::endl;
+ _writeReserve = write;
+ return write;
+}
+
+/**
+ *
+ */
+void WindowedFifo::release() {
+ if (_isHeadReserved) {
+ //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl;
+ _head = _headRoom;
+ _use += _writeReserve;
+ _isHeadReserved = false;
+ }
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::capture(char **destination, unsigned len) {
+
+ //std::cout << "Attempt to capture " << len << " bytes." << std::endl;
+
+ if (_isTailReserved) {
+ //std::cout << "Only one attempt to capture allowed." << std::endl;
+ *destination = 0;
+ return 0;
+ }
+
+ //capture at most as much data as available in the buffer
+ unsigned read = (len <= _use ? len : 0);
+
+ if (read > 0) {
+ //if wrap-around in buffer: return only buffer for the
+ //conntiguous buffer space
+ if (_tail + read > _size) {
+ read = _size - _tail;
+ }
+
+ _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read;
+ *destination = &(_buffer[_tail]);
+ _isTailReserved = true;
+ }
+
+ _readReserve = read;
+ //std::cout << "Captured " << read << " bytes." << std::endl;
+
+ return read;
+}
+
+/**
+ *
+ */
+void WindowedFifo::consume() {
+ if (_isTailReserved) {
+ //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl;
+ _tail = _tailRoom;
+ _use -= _readReserve;
+ _isTailReserved = false;
+ }
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::size() const {
+ return _size;
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::unused() const {
+ return _size - _use;
+}
+
+/**
+ *
+ */
+unsigned WindowedFifo::used() const {
+ return _use;
+}
+
+/*
+ * Get the pointer to the start of the queue
+ */
+char *WindowedFifo::getQueuePointer() {
+ return _buffer;
+}
+
+/*
+ * Has completed a dma read process, i.e. has read out of the queue
+ */
+void WindowedFifo::dmaRead(unsigned len) {
+ if (len == 0) {
+ _blocked = BLOCKED_MAX_NR;
+ } else {
+ _tail = ((unsigned) (_tail + len) % _size);
+ _use -= len;
+ }
+
+ _activeDMA = false;
+}
+
+/*
+ * Start a DMA request, returns the current space one have
+ */
+unsigned WindowedFifo::dmaStart() {
+ _activeDMA = true;
+
+ if (_tail + _use > _size) {
+ return _size - _tail;
+ } else {
+ return _use;
+ }
+}
+
+/*
+ * Is allowed to start a dma request
+ */
+bool WindowedFifo::dmaAllowed() {
+#ifndef STORE_REQUESTS
+ if (_blocked > 0) {
+ _blocked--;
+ return false;
+ } else {
+ return !_activeDMA;
+ }
+#else
+ return !_activeDMA;
+#endif
+}
+
+/**
+ * Is needed for DMA transfers
+ */
+unsigned WindowedFifo::dmaWrite(const void *source, unsigned len) {
+
+ char* buffer = (char*) source;
+
+ if (_head + len < _size) {
+ memcpy(_buffer + _head, buffer, len);
+ } else {
+ // We should never be here!
+ memcpy(_buffer + _head, buffer, _size - _head);
+ memcpy(_buffer, buffer + _size - _head, len - _size + _head);
+ }
+ _use += len;
+ _head = (_head + len) >= _size ? _head + len - _size : _head + len;
+
+ return len;
+}
+
+/**
+ * Test the implementation
+ */
+/*
+ int main() {
+ WindowedFifo *myFifo = new WindowedFifo(16);
+
+ int* buf1;
+ int* buf2;
+ int x = myFifo->reserve((char**)&buf1, 8);
+ *buf1 = 10;
+ *(buf1 + 1) = 20;
+ myFifo->release();
+ int y = myFifo->capture((char**)&buf2, 8);
+ std::cout << "read " << *buf2 << " " << *(buf2 + 1) << std::endl;
+ myFifo->consume();
+
+ for (int j = 0; j < 3; j++) {
+ for (int i = 0; i < 6; i++) {
+ std::cout << "write " << i << " to Fifo. ";
+ int write = myFifo->reserve((char**)&buf1, sizeof(int));
+ if (write == sizeof(int)) {
+ *buf1 = i;
+ myFifo->release();
+ std::cout << "used: " << std::setw(2) << myFifo->used()
+ << ", unused: " << std::setw(2) << myFifo->unused()
+ << ", size: " << std::setw(2) << myFifo->size()
+ << std::endl;
+ } else {
+ std::cout << std::endl;
+ }
+ }
+ for (int i = 0; i < 16; i++) {
+ char* buf3;
+ int read = myFifo->capture((char**)&buf3, sizeof(char));
+ if (read == sizeof(char)) {
+ std::cout << "read " << (unsigned)*buf3 << " from Fifo ";
+ std::cout << "used: " << std::setw(2) << myFifo->used()
+ << ", unused: " << std::setw(2) << myFifo->unused()
+ << ", size: " << std::setw(2) << myFifo->size()
+ << std::endl;
+ myFifo->consume();
+ } else {
+ std::cout << "read nothing from Fifo." << std::endl;
+ }
+
+ }
+ }
+ delete myFifo;
+ return 0;
+ }
+ */
--- /dev/null
+#ifndef _WINDOWEDFIFO_H_
+#define _WINDOWEDFIFO_H_
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../constant.h"
+
+#include "../lib/malloc_align.h"
+#include "../lib/free_align.h"
+
+class WindowedFifo {
+ public:
+ WindowedFifo(unsigned size);
+ virtual ~WindowedFifo();
+
+ // Write
+ virtual unsigned reserve(char** destination, unsigned len);
+ virtual void release();
+
+ // Read
+ virtual unsigned capture(char** destination, unsigned len);
+ virtual void consume();
+
+ // General functions
+ virtual unsigned used() const;
+ virtual unsigned unused() const;
+ virtual unsigned size() const;
+
+ // DMA functions
+ virtual char *getQueuePointer();
+ virtual void dmaRead(unsigned len);
+ virtual unsigned dmaStart();
+ virtual bool dmaAllowed();
+ virtual unsigned dmaWrite(const void *source, unsigned len);
+
+ // Global variables
+ unsigned _inTail;
+
+ protected:
+ char *_buffer; // Pointer to the buffer
+
+ unsigned _head; // Current position of the head
+ unsigned _tail; // Current position of the tail
+ unsigned _headRoom; // HeadRoom pointer
+ unsigned _tailRoom; // Tailroom pointer
+
+ unsigned _size; // Total space of the buffer
+ unsigned _use; // How many data are used in the buffer
+ unsigned _writeReserve; // Number of tokens one is writing
+ unsigned _readReserve; // Number of tokens one is reading
+
+ bool _isHeadReserved; // Head reserved?
+ bool _isTailReserved; // Tail reserved?
+
+ unsigned _blocked; // Blocked number the request has to wait
+ bool _activeDMA; // Is there an active DMA on this buffer
+};
+
+#endif
--- /dev/null
+/*
+ * common.cpp
+ *
+ * Created on: Feb 27, 2009
+ * Author: lschor
+ */
+
+#include "../common.h"
+
+/**
+ Round a number to the alignment of the Cell
+ */
+uint32_t roundDMA(uint32_t number) {
+ if (number > 16)
+ if (number % 16 == 0)
+ return number;
+ else
+ return number + 16 - (number % 16);
+ else if (number > 8)
+ return 16;
+ else if (number > 4)
+ return 8;
+ else if (number > 2)
+ return 4;
+ else if (number > 1)
+ return 2;
+ else
+ return 1;
+}
--- /dev/null
+#include "dolSupport.h"\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned read(void* fifo, void* buf, unsigned len, DOLProcess* p) {\r
+ unsigned int\r
+ pos =\r
+ static_cast<proc_wrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->readPos;\r
+ pos += ((Fifo*) fifo)->read((char *) buf + pos, len - pos);\r
+\r
+ if (pos == len)\r
+ static_cast<proc_wrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->readPos\r
+ = 0;\r
+ else\r
+ static_cast<proc_wrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->readPos\r
+ = pos;\r
+ return pos;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned write(void* fifo, void* buf, unsigned len, DOLProcess* p) {\r
+ unsigned int\r
+ pos =\r
+ static_cast<proc_wrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->writePos;\r
+ pos += ((Fifo*) fifo)->write((char *) buf + pos, len - pos);\r
+\r
+ if (pos == len)\r
+ static_cast<proc_wrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->writePos\r
+ = 0;\r
+ else\r
+ static_cast<proc_wrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->writePos\r
+ = pos;\r
+ return pos;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void DOL_detach(DOLProcess* p) {\r
+ static_cast<proc_wrapper *> ((static_cast<process_data *> (p->wptr))->wrapper)->detach();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned reserve(void* fifo, void** destination, unsigned len,\r
+ DOLProcess* p) {\r
+ return ((WindowedFifo*) fifo)->reserve((char **) destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void release(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*) fifo)->release();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned capture(void* fifo, void** destination, unsigned len,\r
+ DOLProcess* p) {\r
+ return ((WindowedFifo*) fifo)->capture((char **) destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void consume(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*) fifo)->consume();\r
+}\r
+\r
+void createPort(void** port, void* base, int number_of_indices,\r
+ int index0, int range0) {\r
+ *port = (void**) ((void**) base)[index0];\r
+}\r
+\r
+void createPort(void** port, void* base, int number_of_indices,\r
+ int index0, int range0, int index1, int range1) {\r
+ *port = (void**) ((void**) base)[index0 * range1 + index1];\r
+}\r
+\r
+void createPort(void** port, void* base, int number_of_indices,\r
+ int index0, int range0, int index1, int range1, int index2,\r
+ int range2) {\r
+ *port = (void**) ((void**) base)[index0 * range1 * range2 + index1\r
+ * range2 + index2];\r
+}\r
+\r
+void createPort(void** port, void* base, int number_of_indices,\r
+ int index0, int range0, int index1, int range1, int index2,\r
+ int range2, int index3, int range3) {\r
+ *port = (void**) ((void**) base)[index0 * range1 * range2 * range3\r
+ + index1 * range2 * range3 + index2 * range3 + index3];\r
+}\r
--- /dev/null
+#ifndef DOLSUPPORT_H\r
+#define DOLSUPPORT_H\r
+\r
+#include <stdio.h>\r
+\r
+#include "dol.h"\r
+#include "../pt/pt.h"\r
+#include "proc_wrapper.h"\r
+\r
+#include "Fifo.h"\r
+#include "WindowedFifo.h"\r
+\r
+\r
+typedef struct _process_data {\r
+ int lc;\r
+ proc_wrapper *wrapper;\r
+} process_data;\r
+\r
+\r
+#define DOL_read(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), read(port, buf, size, process) == size);\r
+\r
+#define DOL_write(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), write(port, buf, size, process) == size);\r
+\r
+#define DOL_reserve(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), reserve(port, (void**)buf, size, process) == size);\r
+\r
+ //should stall only if the return size is 0!!! (but how, one has to give a return value...)\r
+\r
+#define DOL_release(port, process) \\r
+ release(port, process);\r
+\r
+#define DOL_capture(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), capture(port, (void**)buf, size, process) == size);\r
+\r
+ //should stall only if the return size is 0!!! (but how, one has to give a return value...)\r
+\r
+#define DOL_consume(port, process) \\r
+ consume(port, process);\r
+\r
+\r
+void DOL_detach(DOLProcess* p);\r
+\r
+unsigned write(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+\r
+unsigned read(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+\r
+unsigned reserve(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+\r
+void release(void* fifo, DOLProcess* p);\r
+\r
+unsigned capture(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+\r
+void consume(void* fifo, DOLProcess* p);\r
+\r
+\r
+//macros to deal with iterated ports\r
+/**\r
+ * macro to create a variable to store a port name\r
+ *\r
+ * @param name name of the variable\r
+ */\r
+#define CREATEPORTVAR(name) static Fifo *name\r
+\r
+/**\r
+ * Create the port name of an iterated port based on its basename and the\r
+ * given indices.\r
+ *\r
+ * @param port buffer where the result is stored (created using\r
+ * CREATEPORTVAR)\r
+ * @param base basename of the port\r
+ * @param number_of_indices number of dimensions of the port\r
+ * @param index_range_pairs index and range values for each dimension\r
+ */\r
+\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+ createPort((void**)(&port), base, number_of_indices, index_range_pairs)\r
+\r
+#define GETINDEX(dimension) \\r
+ static_cast<proc_wrapper *>((static_cast<process_data *>(p->wptr))->wrapper)->getIndex(dimension)\r
+\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1, int index2, int range2);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1, int index2, int range2, int index3, int range3);\r
+\r
+#endif\r
--- /dev/null
+/**
+ * proc_wrapper.cpp
+ *
+ * Created on: Feb 24, 2009
+ * Author: lschor
+ */
+
+#include "proc_wrapper.h"
+
+proc_wrapper::proc_wrapper() {
+ _isDetached = false;
+ readPos = 0;
+ writePos = 0;
+}
+
+proc_wrapper::~proc_wrapper() {
+}
+
+/**
+ *
+ */
+void proc_wrapper::init() {
+ _process.init(&_process);
+}
+
+/**
+ *
+ */
+int proc_wrapper::fire() {
+ return _process.fire(&_process);
+}
+
+/**
+ *
+ */
+void proc_wrapper::detach() {
+ _isDetached = true;
+}
+
+/**
+ * Gets an index of a string, where the index must be separated by
+ * a character specified in tokens.
+ * Returns -1, when an error occurs.
+ *
+ * Example:
+ * getIndex("name_1_2", "_", 0) will return 1.
+ * getIndex("name_1_2", "_", 1) will return 2.
+ *
+ * @param string string to parse
+ * @param tokens delimiter of indices
+ * @param indexNumber position of index (starting at 0)
+ */
+int proc_wrapper::getIndex(const char* string, char* tokens,
+ int indexNumber) {
+ char* string_copy;
+ char* token_pointer;
+ int index = 0;
+
+ string_copy = (char*) malloc(sizeof(char) * (strlen(string) + 1));
+ if (!string_copy) {
+ fprintf(stderr, "getIndex(): could not allocate memory.\n");
+ return -1;
+ }
+
+ strcpy(string_copy, string);
+
+ token_pointer = strtok(string_copy, tokens);
+ do {
+ token_pointer = strtok(NULL, tokens);
+ index++;
+ } while (index <= indexNumber && token_pointer != 0);
+
+ if (token_pointer) {
+ index = atoi(token_pointer);
+ free(string_copy);
+ return index;
+ }
+
+ free(string_copy);
+ return -1;
+}
+
+/**
+ * Get the index of this process.
+ * @param indexNumber position of index (starting at 0)
+ */
+int proc_wrapper::getIndex(unsigned indexNumber) const {
+ if (indexNumber < 4) {
+ return _iteratorIndex[indexNumber];
+ }
+ return -1;
+}
--- /dev/null
+/*
+ * proc_wrapper.h
+ *
+ * Created on: Feb 24, 2009
+ * Author: lschor
+ */
+
+#ifndef PROC_WRAPPER_H_
+#define PROC_WRAPPER_H_
+
+#include <spu_intrinsics.h>
+#include <spu_mfcio.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+//CBE Macros
+#define waittag(tag_id) mfc_write_tag_mask(1<<tag_id); \
+ mfc_read_tag_status_all();
+
+#include "../dol.h"
+
+/**
+ * Wrapper for a SPE Process
+ */
+class proc_wrapper {
+public:
+ proc_wrapper();
+ virtual ~proc_wrapper();
+
+ virtual void init();
+ virtual int fire();
+ virtual bool isDetached() { return _isDetached; }
+ virtual void detach();
+ virtual int getIndex(unsigned indexNumber) const;
+
+ //for FIFO access --> current position you are while blocking
+ unsigned int readPos;
+ unsigned int writePos;
+
+protected:
+ char* name;
+ DOLProcess _process;
+ bool _isDetached;
+ int _iteratorIndex[4];
+
+ uint32_t* port_id;
+ uint32_t* port_queue_id;
+ uint32_t number_of_ports;
+ virtual int getIndex(const char* string, char* tokens,
+ int indexNumber);
+};
+
+#endif /* PROC_WRAPPER_H_ */
--- /dev/null
+// -------------------------------------------------------------- \r
+// (C)Copyright 2007, \r
+// International Business Machines Corporation, \r
+// All Rights Reserved.\r
+// -------------------------------------------------------------- \r
+ \r
+#ifndef _spu_mfcio_ext_h_\r
+#define _spu_mfcio_ext_h_\r
+\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <ctype.h>\r
+\r
+#include <spu_intrinsics.h>\r
+#include <spu_mfcio.h>\r
+\r
+static uint32_t msg[4]__attribute__ ((aligned (16)));\r
+\r
+// ==========================================================================\r
+// Definitions\r
+// ==========================================================================\r
+#define SPU_IN_MBOX_OFFSET 0x0C // offset of mailbox status register from control area base\r
+#define SPU_IN_MBOX_OFFSET_SLOT 0x3 // 16B alignment of mailbox status register = (SPU_MBOX_STAT_OFFSET&0xF)>>2\r
+#define SPU_MBOX_STAT_OFFSET 0x14 // offset of mailbox status register from control area base\r
+#define SPU_MBOX_STAT_OFFSET_SLOT 0x1 // 16B alignment of mailbox status register = (SPU_MBOX_STAT_OFFSET&0xF)>>2\r
+\r
+#define SPU_SIG_NOTIFY_OFFSET 0x0C // offset of signal notify 1 or 2 registera from signal notify 1 or 2 areas base\r
+#define SPU_SIG_NOTIFY_OFFSET_SLOT 0x3 // 16B alignment of signal notify 1 or 2 register = (SPU_SIG_NOTIFY_OFFSET&0xF)>>2\r
+\r
+// ==========================================================================\r
+// Functions definitions\r
+// ==========================================================================\r
+\r
+inline int status_mbox(uint64_t ea_mfc, uint32_t tag_id);\r
+inline int status_in_mbox(uint64_t ea_mfc, uint32_t tag_id);\r
+inline int status_out_mbox(uint64_t ea_mfc, uint32_t tag_id);\r
+inline int status_outintr_mbox(uint64_t ea_mfc, uint32_t tag_id);\r
+\r
+int write_in_mbox(uint32_t data, uint64_t ea_mfc, uint32_t tag_id);\r
+int write_signal1(uint32_t data, uint64_t ea_mfc, uint32_t tag_id);\r
+int write_signal2(uint32_t data, uint64_t ea_mfc, uint32_t tag_id);\r
+\r
+// returns the value of mailbox status register of remote SPE\r
+inline int status_mbox(uint64_t ea_mfc, uint32_t tag_id)\r
+{\r
+ uint32_t status[4], idx; \r
+ uint64_t ea_stat_mbox = ea_mfc + SPU_MBOX_STAT_OFFSET;\r
+\r
+ //printf("<SPE: ea_mfc=0x%llx, ea_stat_mbox=0x%llx\n", ea_mfc, ea_stat_mbox );\r
+ \r
+ idx = SPU_MBOX_STAT_OFFSET_SLOT;\r
+ \r
+ mfc_get((void *)&status[idx], ea_stat_mbox, sizeof(uint32_t), tag_id, 0, 0);\r
+ mfc_write_tag_mask(1<<tag_id);\r
+ mfc_read_tag_status_any();\r
+\r
+ //printf("<SPE: Status=0x%x: OutIntrCnt=0x%x, InCnt=0x%x, OutCnt=0x%x\n", status[idx], \r
+ // (status[idx]&0xffff0000)>>16, (status[idx]&0x0000ff00)>>8, (status[idx]&0x000000ff) );\r
+ //printf("<SPE: status_mbox=%d\n", status[idx] );\r
+ \r
+ return status[idx];\r
+}\r
+\r
+// returns the status (counter) of inbound_mailbox of remote SPE\r
+inline int status_in_mbox(uint64_t ea_mfc, uint32_t tag_id)\r
+{\r
+ int status = status_mbox( ea_mfc, tag_id);\r
+ \r
+ status = (status&0x0000ff00)>>8;\r
+ \r
+ //printf("<SPE: status_in_mbox=%d\n", status );\r
+ \r
+ return status;\r
+}\r
+\r
+// returns the status (counter) of outbound_mailbox of remote SPE\r
+inline int status_out_mbox(uint64_t ea_mfc, uint32_t tag_id)\r
+{\r
+ int status = status_mbox( ea_mfc, tag_id);\r
+\r
+ status = (status&0x000000ff);\r
+ \r
+ //printf("<SPE: status_out_mbox=%d\n", status[idx] );\r
+ \r
+ return status;\r
+}\r
+\r
+// returns the status (counter) of inbound_interrupt_mailbox of remote SPE\r
+inline int status_outintr_mbox(uint64_t ea_mfc, uint32_t tag_id)\r
+{\r
+ int status = status_mbox( ea_mfc, tag_id);\r
+\r
+ status = (status&0xffff0000)>>16;\r
+ \r
+ //printf("<SPE: status_outintr_mbox=%d\n", status[idx] );\r
+ \r
+ return status;\r
+}\r
+\r
+// writing to a remote SPE�s inbound mailbox\r
+inline int write_in_mbox(uint32_t data, uint64_t ea_mfc, uint32_t tag_id){\r
+\r
+ int status;\r
+ uint64_t ea_in_mbox = ea_mfc + SPU_IN_MBOX_OFFSET; \r
+ uint32_t mbx[4], idx;\r
+\r
+ idx = SPU_IN_MBOX_OFFSET_SLOT;\r
+ mbx[idx] = data;\r
+ \r
+ while( (status= status_in_mbox(ea_mfc, tag_id))<1);\r
+ \r
+ mfc_put((void *)&mbx[idx], ea_in_mbox, sizeof(uint32_t), tag_id, 0, 0);\r
+ mfc_write_tag_mask(1<<tag_id);\r
+ mfc_read_tag_status_any();\r
+\r
+ //printf("<SPE: write_in_mbox: complete\n" ); \r
+ \r
+ return 1; // number of mailbox being written\r
+}\r
+\r
+// signal a remote SPE�s signal1 register\r
+inline int write_signal1(uint32_t data, uint64_t ea_sig1, uint32_t tag_id)\r
+{\r
+ uint64_t ea_sig1_notify = ea_sig1 + SPU_SIG_NOTIFY_OFFSET; \r
+ uint32_t idx;\r
+\r
+ //printf("<SPE: write_signal1: starts\n" );\r
+ \r
+ //printf("<SPE: write_signal1: ea_mfc=0x%llx, ea_in_mbox=0x%llx\n", ea_sig1, ea_sig1_notify );\r
+ \r
+ idx = SPU_SIG_NOTIFY_OFFSET_SLOT;\r
+ msg[idx] = data;\r
+ \r
+ mfc_sndsig( &msg[idx], ea_sig1_notify, tag_id, 0,0) ;\r
+ mfc_write_tag_mask(1<<tag_id);\r
+ mfc_read_tag_status_any();\r
+\r
+ //printf("<SPE: write_in_mbox: complete\n" ); \r
+ \r
+ return 1; // number of mailbox being written\r
+}\r
+\r
+// signal a remote SPE�s signal1 register\r
+inline int write_signal2(uint32_t data, uint64_t ea_sig2, uint32_t tag_id)\r
+{\r
+ uint64_t ea_sig2_notify = ea_sig2 + SPU_SIG_NOTIFY_OFFSET; \r
+ uint32_t idx;\r
+\r
+ //printf("<SPE: write_signal2: starts\n" );\r
+ \r
+ //printf("<SPE: write_signal2: ea_mfc=0x%llx, ea_in_mbox=0x%llx\n", ea_sig2, ea_sig2_notify );\r
+ \r
+ idx = SPU_SIG_NOTIFY_OFFSET_SLOT;\r
+ msg[idx] = data;\r
+ \r
+ mfc_sndsig( &msg[idx], ea_sig2_notify, tag_id, 0,0) ;\r
+ mfc_write_tag_mask(1<<tag_id);\r
+ mfc_read_tag_status_any();\r
+\r
+ //printf("<SPE: write_in_mbox: complete\n" ); \r
+ \r
+ return 1; // number of mailbox being written\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+#endif\r
+\r
--- /dev/null
+/*
+ * spu_os.h
+ *
+ * Created on: Mar 17, 2009
+ * Author: lschor
+ */
+
+#ifndef SPU_OS_H_
+#define SPU_OS_H_
+
+#include <spu_intrinsics.h>
+#include <spu_mfcio.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <new>
+
+// Include to allocate/free using for DMA transfers
+#include "../lib/malloc_align.h"
+#include "../lib/free_align.h"
+
+// Local includes
+#include "../lib/spu/Fifo.h"
+#include "../lib/common.h"
+//#include "../lib/spu/Communication.h"
+#include "../lib/spu/FastCommunication.h"
+
+// Protothread includes
+#include "../lib/pt/pt.h"
+
+// Context file
+static spu_context ctx_spu __attribute__ ((aligned (128)));
+
+#endif /* SPU_OS_H_ */
--- /dev/null
+/*
+ * Square_wrapper.cpp
+ *
+ * Created on: Feb 27, 2009
+ * Author: lschor
+ */
+
+
+#include "@PROCESSNAME@Wrapper.h"
+#include "../lib/spu/dolSupport.h"
+
+#include "@PROCESSNAME@.c"
+
+@PROCESSNAME@Wrapper::@PROCESSNAME@Wrapper(uint64_t argp) {
+ // reserve DMA tag ID
+ uint32_t tag_id;
+ if((tag_id=mfc_tag_reserve())==MFC_TAG_INVALID){
+ printf("SPE: ERROR - can't reserve a tag ID\n"); return;
+ }
+
+ // Get the context information for the whole system
+ mfc_get((void*) &ctx_proc, argp, sizeof(ctx_proc), tag_id, 0, 0);
+ mfc_write_tag_mask(1<<tag_id);
+ mfc_read_tag_status_all();
+
+ this->name = (char *)_malloc_align((uint32_t)ctx_proc.processNameLen, 4);
+ if(!this->name) {
+ fprintf(stderr,"[SPUProcessWrapper] Memory allocation failure\n");
+ exit(-1);
+ }
+ mfc_get((void *)this->name, ctx_proc.processName, ctx_proc.processNameLen, tag_id, 0, 0);
+ waittag(tag_id);
+
+
+ //initialize the index array
+ for (int i = 0; i < 4; i++) {
+ this->_iteratorIndex[i] = getIndex(this->name, "_", i);
+ }
+
+ try { _state = (LocalState) new @PROCESSNAME_UPPER@_State; }
+ catch(std::bad_alloc &e) {
+ fprintf(stderr, "[SPUProcessWrapper] Memory allocation failure\n");
+ exit(-1);
+ }
+ _process.local = _state;
+ _process.init = @PROCESSNAME@_init;
+ _process.fire = @PROCESSNAME@_fire;
+ _process.wptr = (void*)&_wrapper_data;
+
+ _wrapper_data.wrapper = this;
+
+ // Init the process
+ _process.init(&_process);
+
+ // release tag ID before exiting
+ mfc_tag_release(tag_id);
+}
+
+@PROCESSNAME@Wrapper::~@PROCESSNAME@Wrapper() {
+ // Free the state
+ if (_state)
+ delete (@PROCESSNAME_UPPER@_State*) _state;
+
+ // Free the name of the wrapper
+ _free_align(this->name);
+}
--- /dev/null
+/****************************************************************
+ * Process Wrapper file
+ * Creator: lschor, 2009-02-24
+ * Description: Wrapper for a specific SPE process
+ *
+ * Revision:
+ * - 2009-02-24: Created
+ */
+
+#ifndef @PROCESSNAME@_WRAPPER_H_
+#define @PROCESSNAME@_WRAPPER_H_
+
+// General includes
+#include <spu_intrinsics.h>
+#include <spu_mfcio.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <new>
+
+// Include to allocate/free using for DMA transfers
+#include "../lib/malloc_align.h"
+#include "../lib/free_align.h"
+#include "../lib/spu/Fifo.h"
+#include "../lib/spu/WindowedFifo.h"
+
+// Local includes
+#include "../lib/common.h"
+//#include "../lib/estimation.h"
+
+#include "../lib/spu/proc_wrapper.h"
+
+class @PROCESSNAME@Wrapper;
+
+typedef struct _@PROCESSNAME@_data {
+ int lc;
+ @PROCESSNAME@Wrapper *wrapper;
+} @PROCESSNAME@_data;
+
+class @PROCESSNAME@Wrapper : public proc_wrapper {
+
+// Context file
+public:
+ @PROCESSNAME@Wrapper(uint64_t argp);
+ virtual ~@PROCESSNAME@Wrapper();
+
+ @FIFO@
+
+protected:
+ LocalState _state;
+ process_context ctx_proc __attribute__ ((aligned (128)));
+ @PROCESSNAME@_data _wrapper_data;
+
+};
+
+#endif /* @PROCESSNAME@_WRAPPER_H_ */
--- /dev/null
+/* $Id: ArchDotVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.dot;
+
+import java.util.Iterator;
+
+import dol.datamodel.architecture.ArchiConnection;
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.architecture.HWChannel;
+import dol.datamodel.architecture.Memory;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.architecture.ReadPath;
+import dol.datamodel.architecture.WritePath;
+import dol.datamodel.pn.Process;
+import dol.util.CodePrintStream;
+import dol.visitor.ArchiVisitor;
+
+/**
+ * Helps to generate DOTTY information for architecture resources.
+ */
+public class ArchDotVisitor extends ArchiVisitor
+{
+ /**
+ * Constructor.
+ *
+ * @param printStream print stream to which the contents is written
+ */
+ public ArchDotVisitor(CodePrintStream printStream) {
+ _printStream = printStream;
+ _pnVisitor = new PNDotVisitor(printStream);
+ }
+
+ /**
+ * Print a .dot file in the correct format for DOTTY.
+ *
+ * @param arch architecture that needs to be rendered
+ */
+ public void visitComponent(Architecture arch) {
+ _printStream.printPrefixln("digraph architecture {");
+ _printStream.println();
+ _printStream.prefixInc();
+ _printStream.printPrefixln("ratio = auto;");
+ _printStream.printPrefixln("rankdir = LR;");
+ _printStream.printPrefixln("ranksep = 2;");
+ _printStream.printPrefixln("nodesep = 0.2;");
+ _printStream.printPrefixln("center = true;");
+ _printStream.printPrefixln("");
+ _printStream.printPrefixln("node [ fontsize=12, height=0.4, "
+ + "width=0.4, style=filled, color=\"0.65 0.20 1.00\" ]");
+ _printStream.println();
+
+ //visit all processors
+ Processor processor;
+ Iterator<Processor> processorIter = arch.getProcessorList().iterator();
+ while( processorIter.hasNext() ) {
+ processor = processorIter.next();
+ processor.accept(this);
+ }
+
+ //visit all hw_channels
+ HWChannel chan;
+ Iterator<HWChannel> chanIter = arch.getHWChannelList().iterator();
+ while(chanIter.hasNext()) {
+ chan = chanIter.next();
+ chan.accept(this);
+ }
+
+ //visit all memories
+ Memory mem;
+ Iterator<Memory> memIter = arch.getMemoryList().iterator();
+ while(memIter.hasNext()) {
+ mem = memIter.next();
+ mem.accept(this);
+ }
+
+ //visit all connections
+ ArchiConnection cn;
+ Iterator<ArchiConnection> cnIter = arch.getConnectionList().iterator();
+ while(cnIter.hasNext()) {
+ cn = cnIter.next();
+ cn.accept(this);
+ }
+
+ ReadPath rPath;
+ Iterator<ReadPath> rpIter = arch.getReadPathList().iterator();
+ while(rpIter.hasNext()) {
+ rPath = rpIter.next();
+ rPath.accept(this);
+ }
+
+ WritePath wPath;
+ Iterator<WritePath> wpIter = arch.getWritePathList().iterator();
+ while(wpIter.hasNext()) {
+ wPath = wpIter.next();
+ wPath.accept(this);
+ }
+
+ _printStream.prefixDec();
+ _printStream.println();
+ _printStream.printPrefixln("}");
+ }
+
+ public void visitComponent(HWChannel chan)
+ {
+ _printStream.printPrefixln("subgraph cluster_"
+ + chan.getName().replaceAll("\\.", "") + " {");
+ _printStream.prefixInc();
+ _printStream.printPrefixln("label = \"" + chan.getName() + "\"");
+
+ if (!chan.getPathList().isEmpty()) {
+ Iterator<String> pIter = chan.getPathList().iterator();
+ String path;
+ while (pIter.hasNext()) {
+ path = (String) pIter.next();
+ _printStream.printPrefixln("\"" + path + "_" + chan.getName()
+ + "\" [label=\" " +
+ "\" shape=circle style=solid]");
+ }
+ }
+
+ _printStream.prefixDec();
+ _printStream.printPrefixln("}");
+ _printStream.println();
+ }
+
+ public void visitComponent(Memory mem)
+ {
+ _printStream.printPrefixln("subgraph cluster_"
+ + mem.getName().replaceAll("\\.", "") + " {");
+ _printStream.prefixInc();
+ _printStream.printPrefixln("label = \"" + mem.getName() + "\"");
+
+ if (!mem.getRXBufList().isEmpty()) {
+ Iterator<String> rIter = mem.getRXBufList().iterator();
+ String rxBuf;
+ while (rIter.hasNext()) {
+ rxBuf = (String) rIter.next();
+ _printStream.printPrefixln("\"" + rxBuf.replaceAll("\\.", "")
+ + "_RX\" [label=\"RX"
+ + "\" shape=circle style=dotted]");
+ }
+ }
+
+ if (!mem.getTXBufList().isEmpty()) {
+ Iterator<String> rIter = mem.getTXBufList().iterator();
+ String txBuf;
+ while (rIter.hasNext()) {
+ txBuf = (String) rIter.next();
+ _printStream.printPrefixln("\"" + txBuf.replaceAll("\\.", "")
+ + "_TX\" [label=\"TX"
+ + "\" shape=circle style=dashed]");
+ }
+ }
+
+ if (!mem.getCHBufList().isEmpty()) {
+ Iterator<String> rIter = mem.getCHBufList().iterator();
+ String chBuf;
+ while (rIter.hasNext()) {
+ chBuf = (String) rIter.next();
+ _printStream.printPrefixln("\"" + chBuf.replaceAll("\\.", "")
+ + "_CH\" [label=\"CH"
+ + "\" shape=circle style=bold]");
+ }
+ }
+
+ _printStream.prefixDec();
+ _printStream.printPrefixln("}");
+ _printStream.println();
+ }
+
+
+ public void visitComponent(ArchiConnection cn)
+ {
+ _printStream.printPrefix();
+ _printStream.print("\""
+ + cn.getOrigin().getName().replaceAll("\\.", "") + "\" -> \""
+ + cn.getTarget().getName().replaceAll("\\.", "")
+ + "\" [ color=" + _color + " ];");
+ _printStream.println();
+ }
+
+ public void visitComponent(ReadPath rp)
+ {
+ String rName = rp.getName().replaceAll("\\.", "");
+
+ _printStream.printPrefix();
+ _printStream.print(rName + "_RPath_CH->" );
+
+ Iterator<HWChannel> cIter = rp.getHWChannelList().iterator();
+ while (cIter.hasNext()) {
+ HWChannel channel = cIter.next();
+ _printStream.print(rName + "_RPath_"
+ + channel.getName().replaceAll("\\.", "")
+ + "->");
+ }
+ _printStream.println(rName + "_RX");
+ }
+
+ public void visitComponent(WritePath rp)
+ {
+ String rName = rp.getName().replaceAll("\\.", "");
+
+ _printStream.printPrefix();
+ _printStream.print(rName + "_TX->" );
+
+ Iterator<HWChannel> cIter = rp.getHWChannelList().iterator();
+ while (cIter.hasNext()) {
+ HWChannel channel = cIter.next();
+ _printStream.print(rName + "_WPath_"
+ + channel.getName().replaceAll("\\.", "")
+ + "->");
+ }
+ _printStream.println(rName + "_WPath_CH");
+ }
+
+ /**
+ * Clusters all processes of this processor.
+ */
+ public void visitComponent(Processor processor)
+ {
+ /*
+ _printStream.printPrefix();
+ _printStream.print("\"" + processor.getName() + "\" [ label=\""
+ + processor.getName() + "\", color=" + _color
+ + ", shape=box];");
+ _printStream.println();
+ */
+
+ _printStream.printPrefixln("subgraph cluster_"
+ + processor.getName().replaceAll("\\.", "") + " {");
+ _printStream.prefixInc();
+ _printStream.printPrefixln("label = \"" + processor.getName() + "\"");
+
+ // labeleling clusters with dot2.8 & graphviz2.8 seems buggy
+ //_printStream.printPrefixln("label = \"" + processor.getName()+"\";");
+ if (!processor.getProcessList().isEmpty()) {
+ Iterator<Process> pIter = processor.getProcessList().iterator();
+ while (pIter.hasNext()) {
+ pIter.next().accept(_pnVisitor);
+ }
+ }
+ _printStream.prefixDec();
+ _printStream.printPrefixln("}");
+ _printStream.println();
+ }
+
+ /** DOT Visitor to visit process network resources */
+ protected PNDotVisitor _pnVisitor = null;
+
+ protected String _color = "dimgray";
+}
--- /dev/null
+/* $Id: MapDotVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.dot;
+
+import java.util.Iterator;
+
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Channel;
+import dol.util.CodePrintStream;
+import dol.visitor.MapVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * ".dot" output in order to visualize a mapping using the DOTTY tool.
+ */
+public class MapDotVisitor extends MapVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param printStream print stream to which the contents is written
+ */
+ public MapDotVisitor(CodePrintStream printStream) {
+ _printStream = printStream;
+ _pnVisitor = new PNDotVisitor(printStream);
+ _archiVisitor = new ArchDotVisitor(printStream);
+ }
+
+ /**
+ * Print a .dot file in the correct format for DOTTY.
+ *
+ * @param map process network that needs to be rendered
+ */
+ public void visitComponent(Mapping map) {
+ _printStream.printPrefixln("digraph mapping {");
+ _printStream.println();
+ _printStream.prefixInc();
+ _printStream.printPrefixln("ratio = auto;");
+ _printStream.printPrefixln("rankdir = LR;");
+ _printStream.printPrefixln("ranksep = 0.3;");
+ _printStream.printPrefixln("nodesep = 0.2;");
+ _printStream.printPrefixln("center = true;");
+ _printStream.printPrefixln("");
+ _printStream.printPrefixln("node [ fontsize=12, height=0.4, "
+ + "width=0.4, style=filled, color=\"0.65 0.20 1.00\" ];");
+ _printStream.printPrefixln("edge [ fontsize=10, arrowhead=normal, "
+ + "arrowsize=0.8, style=\"setlinewidth(2)\" ];");
+ _printStream.println();
+
+ //visit all processors
+ Processor processor;
+ Iterator<Processor> processorIter = map.getProcessorList().iterator();
+ while( processorIter.hasNext() )
+ {
+ processor = processorIter.next();
+ processor.accept(_archiVisitor);
+ }
+
+ //visit all channels (from PN)
+ _pnVisitor.setMapping(map);
+ Channel chan;
+ Iterator<Channel> chanIter = map.getPN().getChannelList().iterator();
+ while (chanIter.hasNext() )
+ {
+ chan = chanIter.next();
+ chan.accept(_pnVisitor);
+ }
+
+ _printStream.prefixDec();
+ _printStream.println();
+ _printStream.printPrefixln("}");
+ }
+
+
+ /** DOT Visitor to visit process network resources */
+ protected PNDotVisitor _pnVisitor = null;
+
+ /** DOT Visitor to visit architecture resources */
+ protected ArchDotVisitor _archiVisitor = null;
+}
--- /dev/null
+/* $Id: PNDotVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.dot;
+
+import java.util.Iterator;
+
+import dol.datamodel.mapping.ComputationBinding;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * ".dot" output in order to visualize a PN using the DOTTY tool.
+ */
+public class PNDotVisitor extends PNVisitor {
+
+ Mapping _mapping = null;
+
+ /**
+ * Constructor.
+ *
+ * @param printStream print stream to which the contents is written
+ */
+ public PNDotVisitor(CodePrintStream printStream) {
+ _printStream = printStream;
+ }
+
+ /**
+ * Print a .dot file in the correct format for DOTTY.
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ _printStream.printPrefixln("digraph pn {");
+ _printStream.println();
+ _printStream.prefixInc();
+ _printStream.printPrefixln("ratio = auto;");
+ _printStream.printPrefixln("rankdir = LR;");
+ _printStream.printPrefixln("ranksep = 0.3;");
+ _printStream.printPrefixln("nodesep = 0.2;");
+ _printStream.printPrefixln("center = true;");
+ _printStream.printPrefixln("");
+ _printStream.printPrefixln("node [ fontsize=12, height=0.4, "
+ + "width=0.4, style=filled, color=\"0.65 0.20 1.00\" ];");
+ _printStream.printPrefixln("edge [ fontsize=10, arrowhead=normal, "
+ + "arrowsize=0.8, style=\"setlinewidth(2)\" ];");
+ _printStream.println();
+
+ //visit all processes
+ Iterator<Process> pIter;
+ Process p;
+ pIter = x.getProcessList().iterator();
+ while (pIter.hasNext())
+ {
+ p = pIter.next();
+ p.accept(this);
+ }
+ _printStream.println();
+
+ //visit all channels
+ Iterator<Channel> cIter;
+ Channel c;
+ cIter = x.getChannelList().iterator();
+ while( cIter.hasNext() ) {
+ c = cIter.next();
+ c.accept(this);
+ }
+
+ _printStream.prefixDec();
+ _printStream.println();
+ _printStream.printPrefixln("}");
+ }
+
+ /**
+ * Print a line for the process in the correct format for DOTTY.
+ *
+ * @param x process that needs to be rendered
+ */
+ public void visitComponent(Process x) {
+ //other colors: beige, lightgoldenrod, orange, tan, khaki3,
+ //aliceblue, lightskyblue, lightseagreen, mintcream,
+ //burlywood3, lightblue1, linen, papayawhip, azure1,2,3
+ String color = "lightskyblue";
+
+ _printStream.printPrefix();
+ _printStream.print("\"" + x.getName() + "\" [ label=\""
+ + x.getName() + "\", color=" +
+ color);
+ if (!x.hasInPorts() || !x.hasOutPorts())
+ _printStream.print(", shape=diamond");
+ else
+ _printStream.print(", shape=ellipse");
+ _printStream.print(" ];");
+ _printStream.println();
+ }
+
+ /**
+ * Print a line for the channel in the correct format for DOTTY.
+ *
+ * @param x channel that needs to be rendered
+ */
+ public void visitComponent(Channel x) {
+ String color = "lightblue3";
+
+ //change the color of the channel to indicate whether connection
+ //is on-tile or off-tile
+ if (_mapping != null) {
+ String process1 = _mapping.getPN().getProcess(x.getOrigin().
+ getName()).getName();
+ String process2 = _mapping.getPN().getProcess(x.getTarget().
+ getName()).getName();
+ String processor1 = "";
+ String processor2 = "";
+
+ for (ComputationBinding binding :
+ _mapping.getCompBindList()) {
+ if (binding.getProcess().getName().
+ equals(process1)) {
+ processor1 = binding.getProcessor().getName();
+ } else if (binding.getProcess().getName().
+ equals(process2)) {
+ processor2 = binding.getProcessor().getName();
+ }
+ }
+ if (processor1.equals(processor2)) {
+ } else if (processor1.length() >= 6 && processor2.length() >=6
+ && processor1.substring(0, 6).equals(
+ processor2.substring(0, 6))) {
+ color = "orange";
+ } else {
+ color = "red";
+ }
+ }
+
+
+ Iterator<Port> i;
+ Port port, portNext;
+ i = x.getPortList().iterator();
+
+ port = (Port) i.next();
+
+ portNext = (Port) i.next();
+ _printStream.printPrefix();
+
+ _printStream.print("\"" + port.getPeerResource().getName()
+ + "\" -> " + "\"" + portNext.getPeerResource().getName()
+ + "\" [" );
+ _printStream.print(" label=\"" + x.getName() + "\""
+ + ", color=" + color + " ];");
+ _printStream.println();
+ }
+
+ /**
+ *
+ */
+ public void setMapping(Mapping mapping) {
+ _mapping = mapping;
+ }
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Dotty graphical representation generation.
+This package will generate a dotty representation for a given example.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: HdsMakefileVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.hds;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.Configuration;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a HdS package Makefile.
+ */
+public class HdsMakefileVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of the Makefile
+ */
+ public HdsMakefileVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ * Create a Makefile for the given process network.
+ *
+ * @param x process network that needs to be rendered.
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ ps.println("CXX = g++");
+ ps.println("CC = g++");
+ ps.println();
+ ps.println("PREPROC_MACROS = -D__DOL_ETHZ_GEN__ "
+ + " -DINCLUDE_PROFILER #-DINCLUDE_PERFORMANCE"
+ + " #-DINCLUDE_TRACE");
+ ps.println();
+ ps.println("SYSTEMC_INC = -I" + _ui.getSystemCINC());
+ ps.println("SYSTEMC_LIB = " + _ui.getSystemCLIB());
+ ps.println("MY_LIB_INC = -Ilib -Isc_wrappers -Iprocesses");
+ ps.println("VPATH = lib:sc_wrappers:processes");
+ ps.println();
+ ps.println("CXXFLAGS = -g -O0 -Wall $(PREPROC_MACROS) "
+ + "$(SYSTEMC_INC) $(MY_LIB_INC)");
+ ps.println("CFLAGS = $(CXXFLAGS)");
+ ps.println();
+
+ ps.print("PROCESS_OBJS = dolSupport.o ProcessWrapper.o "
+ + "Fifo.o WindowedFifo.o ");
+
+ for (String basename : x.getProcessBasenames()) {
+ ps.print(basename + "_wrapper.o ");
+ }
+
+ for (Configuration conf : x.getCfgList()) {
+ if (conf.getName().equals("EXTERNAL_SRC")) {
+ ps.print(conf.getValue() + " ");
+ }
+ }
+
+ ps.println("#xmlParser.o Performance_Extraction.o "
+ + "functional_trace.o");
+ ps.println();
+ ps.println("all:" + _name);
+ ps.println();
+ ps.println(_name + ": " + _name + ".o $(PROCESS_OBJS)");
+ ps.print("\t$(CXX) $(CXXFLAGS) -o $@ $^ $(SYSTEMC_LIB) ");
+ for (Configuration conf : x.getCfgList()) {
+ if (conf.getName().equals("DYNAMIC_LINK"))
+ ps.print(conf.getValue() + " ");
+ }
+ ps.println("# -lpthread -lX11 -lrt");
+ ps.println("clean:");
+ ps.println("\t-rm -f *.o core core.* *.core *.tga "
+ + "static_characterization.xml " + _name);
+
+ } catch (Exception e) {
+ System.out.println("HdsMakefileVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ protected String _name = "sc_application";
+}
--- /dev/null
+/* $Id: HdsModuleVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.hds;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.Resource;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * the main program.
+ */
+public class HdsModuleVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of this file
+ */
+ public HdsModuleVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "sc_application.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ _mainPS = new CodePrintStream(file);
+
+ _mainPS.printPrefixln("#include <systemc>");
+ _mainPS.printPrefixln("#include <list>");
+
+ /* begin of profiling: standard i/o file handling routines */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("#include <stdio.h>");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln("#include \"dol_sched_if.h\"");
+ _mainPS.println();
+
+ for (String basename : x.getProcessBasenames()) {
+ _mainPS.printPrefixln("#include \"" + basename
+ + "_wrapper.h\"");
+ }
+ _mainPS.println();
+ _mainPS.printPrefixln("using namespace std;");
+
+ /* begin of profiling: global variables */
+ _mainPS.println();
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("#define PROFILER_OUTPUT_FILENAME \"profile.txt\"");
+ _mainPS.printPrefixln("FILE *profiler_output_file;");
+ _mainPS.printPrefixln("unsigned int profiler_event_counter;");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.println();
+ _mainPS.printPrefixln("class sc_application : public sc_module ");
+ _mainPS.printLeftBracket();
+
+ _mainPS.printPrefixln("public:");
+ _mainPS.printPrefixln("SC_HAS_PROCESS(sc_application);");
+
+ //declare processes
+ _mainPS.println();
+ for (Process p : x.getProcessList()) {
+ _mainPS.printPrefixln(p.getBasename() + "_wrapper "
+ + p.getName() + "_ins"+ ";");
+ _mainPS.printPrefixln("sc_event " + p.getName()
+ + "_event;");
+ }
+ _mainPS.println();
+
+ //define the scheduler
+ _mainPS.printPrefixln("sc_event sched_event;");
+ _mainPS.printPrefixln("list<sc_event* > eventList;");
+ _mainPS.printPrefixln("list<sc_event* >::iterator iter;");
+ _mainPS.println();
+
+ //declare channels
+ _mainPS.println();
+ for (Channel p : x.getChannelList()) {
+ if (p.getType().equals("fifo")) {
+ _mainPS.printPrefixln("Fifo " + p.getName() + "_ins;");
+ } else if (p.getType().equals("wfifo")) {
+ _mainPS.printPrefixln("WindowedFifo " + p.getName() + "_ins;");
+ }
+ }
+ _mainPS.println();
+
+ //model constructor
+ _mainPS.printPrefixln("sc_application(sc_module_name name)");
+
+ //parameter of constructor
+ _mainPS.printPrefix(": sc_module(name)");
+ for (Process p : x.getProcessList()) {
+ _mainPS.println(",");
+ _mainPS.printPrefix(p.getName() + "_ins(\""
+ + p.getName() +"\")");
+ }
+
+ if (x.getChannelList().size() > 0) {
+ for (Channel c : x.getChannelList()) {
+ _mainPS.println(",");
+ _mainPS.printPrefix(c.getName() + "_ins("
+ + "\"" + c.getName() + "\", "
+ + c.getSize() * c.getTokenSize()
+ + ")");
+ }
+ }
+ _mainPS.println("");
+ _mainPS.printLeftBracket();
+
+ //construtor content
+ //build the network
+ for (Channel ch : x.getChannelList()) {
+ ch.accept(this);
+ }
+ _mainPS.println("");
+
+ _mainPS.println("");
+
+ _mainPS.printPrefixln("SC_THREAD(thread_init);");
+ //init thread
+ _mainPS.printPrefixln("SC_THREAD(thread_sched);");
+
+ //declare concurrent non-terminating threads
+ for (Process p : x.getProcessList()) {
+ _mainPS.printPrefixln("SC_THREAD(thread_" +
+ p.getName() + ");");
+ }
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+ //define scheduler thread
+ _mainPS.printPrefixln("void thread_init()");
+ _mainPS.printLeftBracket();
+ //init
+ for (Process p : x.getProcessList()) {
+ _mainPS.printPrefixln(p.getName() + "_ins.initialize();");
+ }
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+
+ //different scheduling algorithm can be put here
+ _mainPS.printPrefixln("void thread_sched()");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("while (1)");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("for (iter=eventList.begin(); iter != "
+ + "eventList.end(); ++iter)");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("sc_event* e = (*iter);");
+ _mainPS.printPrefixln("e->notify();");
+ _mainPS.printRightBracket();
+ _mainPS.printPrefixln("eventList.clear();");
+ _mainPS.printPrefixln("wait(sched_event);");
+ _mainPS.printRightBracket();
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+ //define threads
+ for (Process p : x.getProcessList()) {
+ p.accept(this);
+ }
+
+ /* begin of profiling: initialization function. */
+ /* - opens file */
+ /* - writes a list of all channels with the connected ports to the file. */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("void initialize_profiler()");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("if ((profiler_output_file = fopen(PROFILER_OUTPUT_FILENAME,\"w\"))==NULL)");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("printf(\"Unable to open profiler output file. No profiling output is written.\\n\");");
+ _mainPS.printPrefixln("return;");
+ _mainPS.printRightBracket();
+ //_mainPS.printPrefixln("printf(\"Profiling data is written to %s.\\n\", PROFILER_OUTPUT_FILENAME);");
+ _mainPS.println();
+
+ for (Channel ch : x.getChannelList()) {
+ String outputString = "fprintf(profiler_output_file, \"c " + ch.getName() + " " + ch.getSize();
+ String outputStringAppendix = "";
+ for (Port p : ch.getPortList()) {
+ Port peerPort = (Port)(p.getPeerPort());
+ Resource peerResource = p.getPeerResource();
+
+ if (p.isOutPort()) {
+ // channel.out == process.in
+ outputString += " i " + peerResource.getName() + " %pI";
+ outputStringAppendix += ",(" + peerResource.getName()
+ + "_ins.INPORT_"
+ + peerPort.getBasename()
+ + peerPort.getName().replaceAll(
+ "_([0-9]+)", "[$1]").replaceFirst(
+ peerPort.getBasename(), "") + ")";
+ } else {
+ outputString += " o " + peerResource.getName() + " %pO";
+ outputStringAppendix += ",(" + peerResource.getName()
+ + "_ins.OUTPORT_"
+ + peerPort.getBasename()
+ + peerPort.getName().replaceAll(
+ "_([0-9]+)", "[$1]").replaceFirst(
+ peerPort.getBasename(), "") + ")";
+ }
+ }
+ outputString += "\\n\"" + outputStringAppendix + ");";
+ _mainPS.printPrefixln(outputString);
+ }
+ _mainPS.printRightBracket();
+ _mainPS.printPrefixln("#endif");
+ _mainPS.println();
+ /* end of profiling */
+
+ _mainPS.printRightBracket(); // end of class
+ _mainPS.println(";");
+
+ //create and run the simulator
+ _mainPS.printPrefixln("int sc_main (int argc, char *argv[])");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("sc_report_handler::set_actions(\""
+ + "/IEEE_Std_1666/deprecated\", SC_DO_NOTHING);");
+ _mainPS.printPrefixln("sc_report::register_id("
+ + "5000, "
+ + "\"parameter problem\" );");
+
+ //create an instance of the application model
+ //remove potential whitespaces before using the process
+ //network name as a systemc identifier
+ _mainPS.printPrefixln("sc_application my_app_mdl(\""
+ + x.getName().replaceAll(" ", "") + "\");");
+
+ /* begin of profiling: initialize the profiler */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("my_app_mdl.initialize_profiler();");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln("sc_start(-1,SC_NS);");
+ /* begin of profiling: close the output file */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("if (profiler_output_file != NULL) fclose(profiler_output_file);");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln("return 0;");
+
+ _mainPS.printRightBracket();
+
+ }
+ catch (Exception e) {
+ System.out.println("HdsModuleVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Print a line for the process in the correct format for DOTTY.
+ *
+ * @param x process that needs to be rendered
+ */
+ public void visitComponent(Process x) {
+ _mainPS.printPrefixln("void thread_" + x.getName() + "()");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("while (!" + x.getName()
+ + "_ins.isDetached())");
+ _mainPS.printLeftBracket();
+
+ /* begin of profiling: start event */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("if (profiler_output_file != NULL) fprintf(profiler_output_file, \"%u "+ x.getName() + " started.\\n\", profiler_event_counter++);");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln(x.getName() + "_ins.fire();");
+
+ /* begin of profiling: stop event */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("if (profiler_output_file != NULL) fprintf(profiler_output_file, \"%u "+ x.getName() + " stopped.\\n\", profiler_event_counter++);");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln("eventList.push_back(&" + x.getName()
+ + "_event);");
+ _mainPS.printPrefixln("sched_event.notify();");
+ _mainPS.printPrefixln("wait(" + x.getName() + "_event);");
+
+ _mainPS.printRightBracket();
+ _mainPS.printRightBracket();
+ }
+
+ /**
+ *
+ * @param x channel that needs to be rendered
+ */
+ public void visitComponent(Channel x) {
+ for (Port p : x.getPortList()) {
+ Port peerPort = (Port)(p.getPeerPort());
+ Resource peerResource = p.getPeerResource();
+ if (peerPort.getRange() != null) {
+ if (p.isOutPort()) {
+ _mainPS.printPrefix(peerResource.getName()
+ + "_ins.INPORT_"
+ + peerPort.getBasename()
+ + peerPort.getName().replaceAll(
+ "_([0-9]+)", "[$1]").replaceFirst(
+ peerPort.getBasename(), ""));
+ }
+ else if (p.isInPort()) {
+ _mainPS.printPrefix(peerResource.getName()
+ + "_ins.OUTPORT_"
+ + peerPort.getBasename()
+ + peerPort.getName().replaceAll(
+ "_([0-9]+)", "[$1]").replaceFirst(
+ peerPort.getBasename(), ""));
+ }
+ }
+ else {
+ if (p.isOutPort()) {
+ _mainPS.printPrefix(peerResource.getName()
+ + "_ins.INPORT_" + peerPort.getName());
+ }
+ else if (p.isInPort()) {
+ _mainPS.printPrefix(peerResource.getName()
+ + "_ins.OUTPORT_" + peerPort.getName());
+ }
+ }
+ _mainPS.println(" = &" + x.getName() + "_ins;");
+ }
+ }
+
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+}
--- /dev/null
+/* $Id: HdsProcessVisitor.java 1 2010-02-24 13:03:05Z haidw $$ */
+package dol.visitor.hds;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.SourceCode;
+import dol.util.CodePrintStream;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a wrapper class for a process: process_wrapper.[h/cpp].
+ */
+public class HdsProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir target directory
+ */
+ public HdsProcessVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ Vector<String> pList = new Vector<String>();
+
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ pList.add(basename);
+ p.accept(this);
+ }
+ }
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param p process that needs to be rendered
+ */
+ public void visitComponent(Process p) {
+ try {
+ _createCppFile(p);
+ _createHeaderFile(p);
+ _adaptSources(p);
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _adaptSources(Process p) throws IOException {
+ Sed sed = new Sed();
+ for (Port port : p.getPortList()) {
+ String processHeaderFile;
+
+ for (SourceCode sr : p.getSrcList()) {
+ processHeaderFile = _dir + _delimiter + ".."
+ + _delimiter + "processes" + _delimiter
+ + sr.getLocality().
+ replaceAll("(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ if (port.isOutPort()) {
+ sed.sed(processHeaderFile,
+ "(#define[ ]+PORT_\\w*[ ]+)\"?"
+ + port.getBasename() + "\"?",
+ "$1 " + "((static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))->OUTPORT_"
+ + port.getBasename() + ")");
+
+ }
+ else if (port.isInPort()) {
+ sed.sed(processHeaderFile,
+ "(#define[ ]+PORT_\\w*[ ]+)\"?"
+ + port.getBasename() + "\"?",
+ "$1 " + "((static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))->INPORT_"
+ + port.getBasename() + ")");
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _createCppFile(Process p) throws IOException {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ String newline = System.getProperty("line.separator");
+ String code = "#include \"" + p.getBasename() + "_wrapper.h\""
+ + newline;
+ for (SourceCode sr : p.getSrcList()) {
+ code += "#include \"" + sr.getLocality() + "\"" + newline;
+ }
+ /*
+ for (SourceCode sr : p.getSrcList()) {
+ code += "#include \"" + sr.getLocality().substring(0,
+ sr.getLocality().lastIndexOf(".") + 1) + "h\""
+ + newline;
+ }
+ */
+
+ code += newline;
+
+ code += p.getBasename() + "_wrapper::"
+ + p.getBasename() + "_wrapper(char* name)"
+ + newline;
+ code += " : ProcessWrapper(name) {" + newline;
+ code += " _state = (LocalState)new "
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State;"
+ + newline;
+ code += " _process.local = _state;" + newline;
+ code += " _process.init = " + p.getBasename() + "_init;"
+ + newline;
+ code += " _process.fire = " + p.getBasename() + "_fire;"
+ + newline;
+ code += " _process.wptr = this;" + newline;
+ code += "}" + newline + newline;
+
+ code += p.getBasename() + "_wrapper::~" + p.getBasename()
+ + "_wrapper() {" + newline;
+ code += " if (_state)" + newline;
+ code += " delete ("
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State*)_state;"
+ + newline;
+ code += "}" + newline;
+ ps.printPrefixln(code);
+ }
+
+ protected void _createHeaderFile(Process p)
+ throws IOException {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.h";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ String newline = System.getProperty("line.separator");
+ String code = "#ifndef " + p.getBasename() + "_WRAPPER_H"
+ + newline;
+ code += "#define " + p.getBasename() + "_WRAPPER_H" + newline
+ + newline;
+ code += "#include \"ProcessWrapper.h\"" + newline;
+ code += "#include \"dolSupport.h\"" + newline;
+ code += newline;
+
+ code += "class " + p.getBasename() + "_wrapper : "
+ + "public ProcessWrapper {" + newline;
+ code += " public:" + newline;
+ code += " " + p.getBasename()
+ + "_wrapper(char* name);" + newline;
+ code += " virtual ~" + p.getBasename() + "_wrapper();"
+ + newline;
+
+ Vector<String> portList = new Vector<String>();
+ for (Port port : p.getPortList()) {
+ String basename = port.getBasename();
+
+ if (!portList.contains(basename)) {
+ portList.add(basename);
+
+ if (((Channel)port.getPeerResource()).getType().
+ equals("wfifo")) {
+ code += " WindowedFifo *";
+ } else {
+ code += " Fifo *";
+ }
+ if (!port.getRange().equals("")) {
+ if (port.isOutPort()) {
+ code += "OUTPORT_"
+ + port.getBasename() + "["
+ + port.getRange().replaceAll(
+ ";", "\\]\\[") + "];" + newline;
+ }
+ else if (port.isInPort()) {
+ code += "INPORT_"
+ + port.getBasename() + "["
+ + port.getRange().replaceAll(
+ ";", "\\]\\[") + "];" + newline;
+ }
+ }
+ else {
+ if (port.isOutPort()) {
+ code += "OUTPORT_"
+ + port.getName() + ";" + newline;
+ }
+ else if (port.isInPort()) {
+ code += "INPORT_"
+ + port.getName() + ";" + newline;
+ }
+ }
+ }
+ }
+
+ code += " protected:" + newline;
+ code += " LocalState _state;" + newline;
+ code += "};" + newline + newline;
+ code += "#endif";
+ ps.printPrefixln(code);
+ }
+
+ protected String _dir = null;
+}
--- /dev/null
+/* $Id: HdsVisitor.java 1 2010-02-24 13:03:05Z haidw $$ */
+package dol.visitor.hds;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.util.Copier;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a HdS package.
+ */
+public class HdsVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param packageName name of the HdS directory
+ */
+ public HdsVisitor(String packageName) {
+ _packageName = packageName;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered.
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ _generateDirHierarchy();
+
+ x.accept(new HdsMakefileVisitor(_srcDir));
+ x.accept(new HdsModuleVisitor(_srcDir));
+ x.accept(new HdsProcessVisitor(_wrapperDir));
+ }
+ catch (Exception e) {
+ System.out.println("HdSVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _generateDirHierarchy()
+ throws IOException, FileNotFoundException {
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ _srcDir = _packageName + _delimiter + _srcDirName;
+ dir = new File(_srcDir);
+ dir.mkdirs();
+
+ _libDir = _srcDir + _delimiter + _libDirName;
+ dir = new File(_libDir);
+ dir.mkdirs();
+
+ _processDir = _srcDir + _delimiter + _processDirName;
+ dir = new File(_processDir);
+ dir.mkdirs();
+
+ _wrapperDir = _srcDir + _delimiter + _wrapperDirName;
+ dir = new File(_wrapperDir);
+ dir.mkdirs();
+
+ //copy library files
+ File source = new File(_ui.getMySystemCLib().
+ replaceAll("systemC", "hds"));
+ File destination = new File(_libDir);
+ new Copier().copy(source, destination);
+
+ //copy process source code
+ source = new File(_srcDirName);
+ destination = new File(_processDir);
+ new Copier().copy(source, destination);
+ }
+
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+
+ protected String _libDir = "";
+ protected static String _libDirName = "lib";
+
+ protected String _processDir = "";
+ protected static String _processDirName = "processes";
+
+ protected String _wrapperDir = "";
+ protected static String _wrapperDirName = "sc_wrappers";
+
+ protected String _threadPostfix = "_thread";
+
+ protected CodePrintStream _mainPS = null;
+}
--- /dev/null
+#include "Fifo.h"\r
+\r
+/**\r
+ *\r
+ */\r
+Fifo::Fifo(char* name, unsigned size = 18) {\r
+ //std::cout << "Create Fifo." << std::endl;\r
+ //except at the beginning, _head and _tail must never overlap,\r
+ //otherwise one does not know whether the buffer is full or\r
+ //empty. to have nevertheless a buffer with the given capacity,\r
+ //a buffer with one more element is allocated.\r
+ _size = size;\r
+ _buffer = new char[_size];\r
+ //_head = 0;\r
+ _use = 0;\r
+ _tail = 0;\r
+ _name = new char[strlen(name) + 1];\r
+ strcpy(_name, name);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+Fifo::~Fifo() {\r
+ //std::cout << "Delete Fifo." << std::endl;\r
+ if (_buffer) {\r
+ delete _buffer;\r
+ }\r
+ if (_name) {\r
+ delete _name;\r
+ }\r
+ _buffer = 0;\r
+ //_head = 0;\r
+ _use = 0;\r
+ _tail = 0;\r
+ _name = 0;\r
+ //std::cout << "Deleted Fifo." << std::endl;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::read(void *destination, unsigned len) {\r
+ char* buffer = (char*)destination;\r
+ unsigned read = 0;\r
+ //std::cout << "Try to read " << len << " bytes from Fifo " << _name << "." << std::endl;\r
+\r
+\r
+ while (read < len) {\r
+ while( _use < len)\r
+ wait(_writeEvent);\r
+ unsigned tocopy = (len - read <= _use ? len - read : _use);\r
+\r
+ if ((unsigned)_tail + tocopy < _size) {\r
+ memcpy(buffer, _buffer + (unsigned)_tail, tocopy);\r
+ }\r
+ else {\r
+ memcpy(buffer, _buffer + (unsigned)_tail, _size - (unsigned)_tail);\r
+ memcpy(buffer + _size - (unsigned)_tail, _buffer, tocopy - _size + (unsigned)_tail);\r
+ }\r
+\r
+ read += tocopy;\r
+ buffer += tocopy;\r
+ _tail = (_tail + tocopy) % _size;\r
+ _use -= read;\r
+ _readEvent.notify();\r
+ }\r
+\r
+ /*while (read < len) {\r
+ if (used() == 0) {\r
+ wait(_writeEvent);\r
+ } else if ((len - read) < used()) {\r
+ while (read < len) {\r
+ unsigned tocopy = (len - read + _tail >= _size) ? _size - _tail : len - read;\r
+ memcpy(buffer, _buffer + _tail, tocopy);\r
+ _tail = (_tail + tocopy) % _size;\r
+ read += tocopy;\r
+ buffer += tocopy;\r
+ }\r
+ _readEvent.notify();\r
+ } else {\r
+ *buffer++ = *(_buffer + _tail % _size);\r
+ _tail = (_tail + 1) % _size;\r
+ read++;\r
+ _readEvent.notify();\r
+ }\r
+ }*/\r
+\r
+ //std::cout << "Read " << read << " bytes from Fifo " << _name << "." << std::endl;\r
+ return read;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::write(const void *source, unsigned len) {\r
+ char* buffer = (char*)source;\r
+ unsigned write = 0;\r
+ unsigned head = (_tail + _use) % _size;\r
+ //std::cout << "Try to write " << len << " bytes to Fifo " << _name << std::endl;\r
+\r
+ while (write < len) {\r
+ while (unused() < len) \r
+ wait(_readEvent);\r
+ unsigned tocopy = (len - write <= unused() ? len - write : unused());\r
+\r
+ if (head + tocopy < _size) {\r
+ memcpy(_buffer + head, buffer, tocopy);\r
+ }\r
+ else {\r
+ memcpy(_buffer + head, buffer, _size - head);\r
+ memcpy(_buffer, buffer + _size - head, tocopy - _size + head);\r
+ }\r
+\r
+ write += tocopy;\r
+ buffer += tocopy;\r
+ head = (head + tocopy) % _size;\r
+ _use += write;\r
+ _writeEvent.notify();\r
+ }\r
+\r
+ /* while (write < len) {\r
+ if (unused() == 0) {\r
+ wait(_readEvent);\r
+ } else if ((len - write) < unused()) {\r
+ while (write < len) {\r
+ unsigned tocopy = (len - write + _head >= _size) ? _size - _head : len - write;\r
+ memcpy(_buffer + _head, buffer, tocopy);\r
+ _head = (_head + tocopy) % _size;\r
+ write += tocopy;\r
+ buffer += tocopy;\r
+ }\r
+ _writeEvent.notify();\r
+ } else {\r
+ *(_buffer + (unsigned)(_head) % _size) = *buffer++;\r
+ _head = (_head + 1) % _size;\r
+ write++;\r
+ _writeEvent.notify();\r
+ }\r
+ }*/\r
+\r
+ //std::cout << "Wrote " << write << " bytes to Fifo " << _name << "." << std::endl;\r
+ return write;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::size() const {\r
+ return (_size);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::unused() const {\r
+ return (_size) - _use;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::used() const {\r
+ return _use;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+char* Fifo::getName() const {\r
+ return _name;\r
+}\r
+\r
+/**\r
+ * Test the implementation\r
+ */\r
+/*\r
+class producer : public sc_module\r
+{\r
+ public:\r
+ Fifo *fifo;\r
+\r
+ SC_HAS_PROCESS(producer);\r
+\r
+ producer(sc_module_name name) : sc_module(name)\r
+ {\r
+ SC_THREAD(main);\r
+ }\r
+\r
+ void main()\r
+ {\r
+ const char *str =\r
+ "Visit www.systemc.org and see what SystemC can do for you today!\n";\r
+\r
+ while (*str) {\r
+ fifo->write((void*)str++, 4);\r
+ }\r
+ }\r
+};\r
+\r
+class consumer : public sc_module\r
+{\r
+ public:\r
+ Fifo *fifo;\r
+\r
+ SC_HAS_PROCESS(consumer);\r
+\r
+ consumer(sc_module_name name) : sc_module(name)\r
+ {\r
+ SC_THREAD(main);\r
+ }\r
+\r
+ void main()\r
+ {\r
+ char c;\r
+ cout << endl << endl;\r
+\r
+ while (true) {\r
+ fifo->read(&c, 4);\r
+ cout << c << flush;\r
+\r
+ if (fifo->used() == 1)\r
+ cout << "<1>" << flush;\r
+ if (fifo->used() == 9)\r
+ cout << "<9>" << flush;\r
+ }\r
+ }\r
+};\r
+\r
+class top : public sc_module\r
+{\r
+ public:\r
+ Fifo *fifo_inst;\r
+ producer *prod_inst;\r
+ consumer *cons_inst;\r
+\r
+ top(sc_module_name name) : sc_module(name)\r
+ {\r
+ fifo_inst = new Fifo("myfifo", 10);\r
+\r
+ prod_inst = new producer("producer");\r
+ prod_inst->fifo = fifo_inst;\r
+\r
+ cons_inst = new consumer("consumer");\r
+ cons_inst->fifo = fifo_inst;\r
+ }\r
+};\r
+\r
+int sc_main (int argc , char *argv[]) {\r
+ top top1("top");\r
+ sc_start();\r
+ return 0;\r
+}\r
+*/\r
--- /dev/null
+#ifndef _FIFO_H_\r
+#define _FIFO_H_\r
+\r
+#include "systemc.h"\r
+\r
+class Fifo {\r
+ public:\r
+ Fifo(char* name, unsigned size);\r
+ virtual ~Fifo();\r
+\r
+ virtual unsigned read(void *destination, unsigned len);\r
+ virtual unsigned write(const void *source, unsigned len);\r
+ virtual unsigned used() const;\r
+ virtual unsigned unused() const;\r
+ virtual unsigned size() const;\r
+ virtual char* getName() const;\r
+\r
+ protected:\r
+ char *_buffer;\r
+ //unsigned _head;\r
+ unsigned _tail;\r
+ unsigned _size;\r
+ unsigned _use; \r
+ char *_name;\r
+ sc_event _readEvent;\r
+ sc_event _writeEvent;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#include "Performance_Extraction.h"
+#include <string>
+#include <fstream>
+
+
+Performance_Extraction performance_extraction("static_characterization.xml");
+
+/**
+ *
+ */
+int get_current_time(CURRENT_TIME *current_time_ptr)
+{
+ return clock_gettime(CLOCK_REALTIME, &(current_time_ptr->ts));
+}
+
+
+/**
+ *
+ */
+double sub_time(CURRENT_TIME *start_time_ptr, CURRENT_TIME *end_time_ptr)
+{
+ CURRENT_TIME diff_time;
+ double time_ns;
+
+ diff_time.ts.tv_sec = end_time_ptr->ts.tv_sec - start_time_ptr->ts.tv_sec;
+ diff_time.ts.tv_nsec = end_time_ptr->ts.tv_nsec - start_time_ptr->ts.tv_nsec;
+ time_ns = diff_time.ts.tv_sec * 1E+9 + diff_time.ts.tv_nsec;
+
+ return time_ns;
+}
+
+
+/**
+ *
+ */
+Process_Performance::Process_Performance(const char *name)
+{
+ strcpy(_process_name, name);
+ _head = NULL;
+ _tail = NULL;
+}
+
+
+/**
+ *
+ */
+Process_Performance::~Process_Performance()
+{
+ COMP_ENTRY *temp;
+ DBGPRINT;
+ while (_head != NULL) {
+ temp = _head;
+ _head = _head->next;
+ delete temp;
+ }
+}
+
+
+/**
+ *
+ */
+const char *Process_Performance::get_name()
+{
+ return _process_name;
+}
+
+
+/**
+ *
+ */
+COMP_ENTRY *Process_Performance::get_head_entry()
+{
+ return _head;
+}
+
+
+/**
+ *
+ */
+COMP_ENTRY *Process_Performance::get_entry(int start_line, int end_line)
+{
+ COMP_ENTRY *temp = NULL;
+ temp = _head;
+ while (temp != NULL) {
+ if ((temp->start_line == start_line) && (temp->end_line == end_line)) {
+ break;
+ }
+ temp = temp->next;
+ }
+
+ return temp;
+}
+
+
+/**
+ *
+ */
+COMP_ENTRY *Process_Performance::add_entry(int start_line, int end_line)
+{
+ COMP_ENTRY *temp = NULL;
+ temp = get_entry(start_line, end_line);
+ if (temp == NULL) {
+ temp = new COMP_ENTRY;
+
+ if (_head == NULL) {
+ _head = temp;
+ _tail = temp;
+ temp->next = NULL;
+ } else {
+ _tail->next = temp;
+ _tail = temp;
+ temp->next = NULL;
+ }
+ temp->start_line = start_line;
+ temp->end_line = end_line;
+ temp->total_computation_time = 0;
+ temp->called_times = 0;
+ }
+
+ return temp;
+}
+
+
+/**
+ *
+ */
+int Process_Performance::set_entry(int start_line, int end_line,
+ CURRENT_TIME *start_time_ptr,
+ CURRENT_TIME *end_time_ptr)
+{
+ int ret = 0;
+ COMP_ENTRY *temp;
+ double computation_time;
+ computation_time = sub_time(start_time_ptr, end_time_ptr);
+ temp = get_entry(start_line, end_line);
+ if (temp == NULL) {
+ temp = add_entry(start_line, end_line);
+ }
+
+ temp->total_computation_time += computation_time;
+ temp->called_times++;
+
+ return ret;
+}
+
+
+/**
+ *
+ */
+Performance_Extraction::Performance_Extraction(const char *chr_file_name)
+{
+ strcpy(_chr_file_name, chr_file_name);
+}
+
+
+/**
+ *
+ */
+Performance_Extraction::~Performance_Extraction()
+{
+ Process_Performance *process_performance_ptr;
+
+#ifdef INCLUDE_PERFORMANCE
+ //strcpy(_processor_type, "DSP");
+ //add_to_xml_file(_chr_file_name);
+ //strcpy(_processor_type, "RISC");
+ //add_to_xml_file(_chr_file_name);
+
+ write_to_xml_file(_chr_file_name);
+#endif
+
+ for (_iter_process_performance = _list_process_performance.begin();
+ _iter_process_performance != _list_process_performance.end();
+ _iter_process_performance++)
+ {
+ process_performance_ptr = *_iter_process_performance;
+ delete process_performance_ptr;
+ }
+ _list_process_performance.clear();
+
+}
+
+
+/**
+ *
+ */
+int Performance_Extraction::add_computation_performance(
+ const char *process_name, int start_line, int end_line,
+ CURRENT_TIME *start_time_ptr, CURRENT_TIME *end_time_ptr)
+{
+ int ret = 0;
+ Process_Performance *process_performance_ptr;
+
+ process_performance_ptr = get_process_performance(process_name);
+ if (process_performance_ptr == NULL) {
+ process_performance_ptr = new Process_Performance(process_name);
+ _list_process_performance.push_back(process_performance_ptr);
+ }
+
+ process_performance_ptr->set_entry(start_line, end_line,
+ start_time_ptr, end_time_ptr);
+
+ return ret;
+}
+
+
+/**
+ *
+ */
+Process_Performance *Performance_Extraction::get_process_performance(
+ const char *process_name)
+{
+ Process_Performance *process_performance_ptr = NULL;
+
+ for (_iter_process_performance = _list_process_performance.begin();
+ _iter_process_performance != _list_process_performance.end();
+ _iter_process_performance++) {
+ process_performance_ptr = *_iter_process_performance;
+ if (strcmp(process_performance_ptr->get_name(), process_name) == 0) {
+ break;
+ }
+ }
+
+ if (_iter_process_performance == _list_process_performance.end()) {
+ process_performance_ptr = NULL;
+ }
+
+ return process_performance_ptr;
+}
+
+
+/**
+ * write performance data into XML file. (identical to add_to_xml_file()
+ * if file does not exist).
+ */
+int Performance_Extraction::write_to_xml_file(const char *chr_file_name)
+{
+ char start_line_str[NAME_LENGTH];
+ char end_line_str[NAME_LENGTH];
+ char computation_time_str[NAME_LENGTH];
+ double computation_time;
+ Process_Performance *process_performance_ptr;
+ COMP_ENTRY *comp_entry;
+
+ //create xml
+ string text = "<?xml version=\"1.0\"?>\n<characterization>\n";
+ for (_iter_process_performance = _list_process_performance.begin();
+ _iter_process_performance != _list_process_performance.end();
+ _iter_process_performance++) {
+ process_performance_ptr = *_iter_process_performance;
+
+ text += " <process name=\"";
+ text += process_performance_ptr->get_name();
+ text += "\">\n";
+
+ for (comp_entry = process_performance_ptr->get_head_entry();
+ comp_entry != NULL;
+ comp_entry = comp_entry->next) {
+ sprintf(start_line_str, "%d", comp_entry->start_line);
+ sprintf(end_line_str, "%d", comp_entry->end_line);
+
+ //hack to eliminate the overhead of system call clock_gettime.
+ //computation_time is nano sec. To get cycles, need to mutiply
+ //by the frequency of cpu. result is in cycles.
+ computation_time = (comp_entry->total_computation_time
+ / comp_entry->called_times - SYS_OVERHEAD)
+ * HOST_FREQUENCY;
+ if (computation_time < 0) {
+ computation_time = 0;
+ }
+ sprintf(computation_time_str, "%.0f", computation_time);
+
+ text += " <computation start=\"";
+ text += start_line_str;
+ text += "\" end=\"";
+ text += end_line_str;
+ text += "\">\n";
+ text += " <processor type=\"DSP\" time=\"";
+ text += computation_time_str;
+ text += "\"/>\n";
+ text += " <processor type=\"RISC\" time=\"";
+ text += computation_time_str;
+ text += "\"/>\n";
+ text += " </computation>\n";
+ }
+ text += " </process>\n";
+ }
+ text += " <communication name=\"read\">\n";
+ text += " <processor type=\"DSP\" time=\"2\"/>\n";
+ text += " <processor type=\"RISC\" time=\"2\"/>\n";
+ text += " </communication>\n";
+ text += " <communication name=\"write\">\n";
+ text += " <processor type=\"DSP\" time=\"2\"/>\n";
+ text += " <processor type=\"RISC\" time=\"2\"/>\n";
+ text += " </communication>\n";
+ text += "</characterization>\n";
+
+ //write xml to file
+ std::ofstream out(chr_file_name, ios::out);
+ if (!out) {
+ printf("Cannot open file %s. Return.\n", chr_file_name);
+ return -1;
+ }
+ out.write(text.c_str(), text.size());
+ out.close();
+ return 0;
+}
+
+
+/**
+ * add performance data to existing XML file (or create new one if file
+ * does not exist).
+ */
+int Performance_Extraction::add_to_xml_file(const char *chr_file_name)
+{
+ int ret = 0;
+ XMLNode file_node;
+ XMLNode root_node;
+ XMLNode process_node;
+ XMLNode comp_node;
+ int computation_index = 0;
+ XMLNode processor_node;
+ XMLNode read_node;
+ XMLNode write_node;
+
+ Process_Performance *process_performance_ptr;
+ COMP_ENTRY *comp_entry;
+
+ char start_line_str[NAME_LENGTH];
+ char end_line_str[NAME_LENGTH];
+ char computation_time_str[NAME_LENGTH];
+ double computation_time;
+
+ file_node = XMLNode::parseFile(chr_file_name);
+ if (file_node.isEmpty()) {
+ file_node = XMLNode::createXMLTopNode("xml", TRUE);
+ file_node.addAttribute("version", "1.0");
+ root_node = file_node.addChild("characterization");
+ }
+
+ root_node = file_node.getChildNode();
+ if (root_node.isEmpty()) {
+ ret = -1;
+ printf("Open characterization file error\n");
+ return ret;
+ }
+
+ for (_iter_process_performance = _list_process_performance.begin();
+ _iter_process_performance != _list_process_performance.end();
+ _iter_process_performance++) {
+ process_performance_ptr = *_iter_process_performance;
+
+ printf("%s\n", process_performance_ptr->get_name());
+
+ process_node = root_node.getChildNodeWithAttribute(
+ "process", "name", process_performance_ptr->get_name());
+ if (process_node.isEmpty())
+ {
+ process_node = root_node.addChild("process");
+ process_node.addAttribute(
+ "name",process_performance_ptr->get_name());
+ }
+
+ for (comp_entry = process_performance_ptr->get_head_entry();
+ comp_entry != NULL;
+ comp_entry = comp_entry->next) {
+ sprintf(start_line_str, "%d", comp_entry->start_line);
+ sprintf(end_line_str, "%d", comp_entry->end_line);
+
+ printf("%d %d\n", comp_entry->start_line, comp_entry->end_line);
+
+ /* Hack to eliminate the overhead of system call clock_gettime.
+ computation_time is nano sec. To get cycles, need to mutiply
+ by the frequency of cpu.
+ result is cycles */
+ computation_time = (comp_entry->total_computation_time
+ / comp_entry->called_times - SYS_OVERHEAD)
+ * HOST_FREQUENCY;
+
+ if (computation_time < 0) {
+ computation_time = 0;
+ }
+
+ sprintf(computation_time_str, "%.0f", computation_time);
+ computation_index = 0;
+ comp_node = process_node.getChildNode("computation",
+ computation_index++);
+ while (!comp_node.isEmpty()) {
+ if (strcmp(comp_node.getAttribute("start"),start_line_str)==0
+ && strcmp(comp_node.getAttribute("end"),end_line_str)==0) {
+ break;
+ }
+
+ comp_node = process_node.getChildNode("computation",
+ computation_index++);
+ }
+
+ if (comp_node.isEmpty()) {
+ comp_node = process_node.addChild("computation");
+ comp_node.addAttribute("start", start_line_str);
+ comp_node.addAttribute("end", end_line_str);
+ }
+
+ processor_node = comp_node.getChildNodeWithAttribute("processor", "type", _processor_type);
+ if (processor_node.isEmpty()) {
+ processor_node = comp_node.addChild("processor");
+ processor_node.addAttribute("type", _processor_type);
+ processor_node.addAttribute("time", computation_time_str);
+ }
+ }
+ }
+
+ read_node = root_node.getChildNodeWithAttribute("communication",
+ "name", "read");
+ if (read_node.isEmpty()) {
+ read_node = root_node.addChild("communication");
+ read_node.addAttribute("name", "read");
+ }
+
+ processor_node = read_node.getChildNodeWithAttribute("processor",
+ "type",
+ _processor_type);
+ if (processor_node.isEmpty()) {
+ processor_node = read_node.addChild("processor");
+ processor_node.addAttribute("type", _processor_type);
+ processor_node.addAttribute("time", "2");
+ }
+
+ write_node = root_node.getChildNodeWithAttribute("communication",
+ "name", "write");
+ if (write_node.isEmpty()) {
+ write_node = root_node.addChild("communication");
+ write_node.addAttribute("name", "write");
+ }
+
+ processor_node = write_node.getChildNodeWithAttribute("processor",
+ "type",
+ _processor_type);
+ if (processor_node.isEmpty()) {
+ processor_node = write_node.addChild("processor");
+ processor_node.addAttribute("type", _processor_type);
+ processor_node.addAttribute("time", "2");
+ }
+
+ file_node.writeToFile(chr_file_name);
+ return 0;
+}
--- /dev/null
+#ifndef _PERFORMANCE_EXTRACTION_H
+#define _PERFORMANCE_EXTRACTION_H
+
+#include <sys/time.h>
+#include <time.h>
+#include "trace.h"
+
+#define SYS_OVERHEAD 1400 //what should be exact vale
+#define HOST_FREQUENCY 3 //Ghz
+
+typedef struct COMP_ENTRY {
+ int start_line;
+ int end_line;
+ double total_computation_time;
+ int called_times;
+ COMP_ENTRY *next;
+} COMP_ENTRY;
+
+typedef struct CURRENT_TIME {
+ struct timespec ts;
+}CURRENT_TIME;
+
+extern int get_current_time(CURRENT_TIME *current_time_ptr);
+extern double sub_time(CURRENT_TIME *start_time_ptr, CURRENT_TIME *end_time_ptr);
+
+class Process_Performance
+{
+private:
+ char _process_name[NAME_LENGTH];
+ COMP_ENTRY *_head;
+ COMP_ENTRY *_tail;
+
+public:
+ Process_Performance(const char *process_name);
+ ~Process_Performance();
+
+ const char *get_name();
+ COMP_ENTRY * add_entry(int start_line, int end_line);
+ int set_entry(int start_line, int end_line, CURRENT_TIME *start_time_ptr,
+ CURRENT_TIME *end_time_ptr);
+ COMP_ENTRY *get_entry(int start_line, int end_line);
+ COMP_ENTRY *get_head_entry();
+};
+
+class Performance_Extraction
+{
+private:
+ char _processor_type[NAME_LENGTH];
+ char _chr_file_name[NAME_LENGTH];
+ list<Process_Performance *> _list_process_performance;
+ list<Process_Performance *>::iterator _iter_process_performance;
+
+public:
+ Performance_Extraction(const char *chr_file_name);
+ ~Performance_Extraction();
+
+ int add_computation_performance(const char *process_name, int start_line,
+ int end_line, CURRENT_TIME *start_time_ptr,
+ CURRENT_TIME *end_time_ptr);
+ Process_Performance *get_process_performance(const char *process_name);
+ int write_to_xml_file(const char *chr_file_name);
+ int add_to_xml_file(const char *chr_file_name);
+};
+
+extern Performance_Extraction performance_extraction;
+
+#endif
--- /dev/null
+#include "ProcessWrapper.h"\r
+#include "dolSupport.h"\r
+\r
+/**\r
+ *\r
+ */\r
+ProcessWrapper::ProcessWrapper(\r
+ sc_module_name name = sc_gen_unique_name("process"))\r
+ : sc_module(name) {\r
+\r
+ _name = new char[strlen(name) + 1];\r
+ strcpy(_name, name);\r
+\r
+ _isDetached = false;\r
+ for (int i = 0; i < 4; i++) {\r
+ _iteratorIndex[i] = getIndex(_name, "_", i);\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+ProcessWrapper::~ProcessWrapper() {\r
+ if (_name) {\r
+ delete _name;\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ProcessWrapper::initialize() {\r
+ _process.init(&_process);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+int ProcessWrapper::fire()\r
+{\r
+ int returnValue;\r
+\r
+ #ifdef INCLUDE_TRACE\r
+ start_line = -1;\r
+ #endif\r
+\r
+ #ifdef INCLUDE_PERFORMANCE\r
+ start_line = -1;\r
+ get_current_time(&start_time);\r
+ #endif\r
+\r
+ returnValue = _process.fire(&_process);\r
+\r
+ #ifdef INCLUDE_TRACE\r
+ end_line = -1;\r
+ dol_functional_trace.create_computation_event(basename(),\r
+ start_line, end_line);\r
+ #endif\r
+\r
+ #ifdef INCLUDE_PERFORMANCE\r
+ get_current_time(&end_time);\r
+ end_line = -1;\r
+ performance_extraction.add_computation_performance(basename(),\r
+ start_line, end_line, &start_time, &end_time);\r
+ #endif\r
+\r
+ return returnValue;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void ProcessWrapper::detach() {\r
+ _isDetached = true;\r
+}\r
+\r
+\r
+/**\r
+ * Gets an index of a string, where the index must be separated by\r
+ * a character specified in tokens.\r
+ * Returns -1, when an error occurs.\r
+ *\r
+ * Example:\r
+ * getIndex("name_1_2", "_", 0) will return 1.\r
+ * getIndex("name_1_2", "_", 1) will return 2.\r
+ *\r
+ * @param string string to parse\r
+ * @param tokens delimiter of indices\r
+ * @param indexNumber position of index (starting at 0)\r
+ */\r
+int ProcessWrapper::getIndex(const char* string, char* tokens,\r
+ int indexNumber) const {\r
+ char* string_copy;\r
+ char* token_pointer;\r
+ int index = 0;\r
+\r
+ string_copy = (char*) malloc(sizeof(char) * (strlen(string) + 1));\r
+ if (!string_copy) {\r
+ fprintf(stderr, "getIndex(): could not allocate memory.\n");\r
+ return -1;\r
+ }\r
+\r
+ strcpy(string_copy, string);\r
+\r
+ token_pointer = strtok(string_copy, tokens);\r
+ do {\r
+ token_pointer = strtok(NULL, tokens);\r
+ index++;\r
+ } while (index <= indexNumber && token_pointer != 0);\r
+\r
+ if (token_pointer) {\r
+ index = atoi(token_pointer);\r
+ free(string_copy);\r
+ return index;\r
+ }\r
+\r
+ return -1;\r
+}\r
+\r
+\r
+/**\r
+ * Get the index of this process.\r
+ * @param indexNumber position of index (starting at 0)\r
+ */\r
+int ProcessWrapper::getIndex(unsigned indexNumber) const {\r
+ if (indexNumber < 4) {\r
+ return _iteratorIndex[indexNumber];\r
+ }\r
+ return -1;\r
+}\r
+\r
+\r
+/**\r
+ * Get the name of this process.\r
+ */\r
+char* ProcessWrapper::getName() const {\r
+ return _name;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+#ifdef INCLUDE_PROFILER\r
+void ProcessWrapper::addToProfile(const char *event, void *port,\r
+ int length) {\r
+ if (profiler_output_file != NULL) {\r
+ fprintf(profiler_output_file, "%u %s %s %p%s %d\n",\r
+ profiler_event_counter++, _name, event, port, (event[0] == 'r') ? "I" : "O",\r
+ length);\r
+\r
+ } else {\r
+ printf("profiler_output_file does not exist");\r
+ }\r
+}\r
+#endif\r
--- /dev/null
+#ifndef _PROCESSWRAPPER_H_\r
+#define _PROCESSWRAPPER_H_\r
+\r
+#include "systemc.h"\r
+#include "dol.h"\r
+#include "dol_sched_if.h"\r
+#include "Fifo.h"\r
+#include "WindowedFifo.h"\r
+#include "functional_trace.h"\r
+#include "Performance_Extraction.h"\r
+\r
+\r
+#ifdef INCLUDE_PROFILER\r
+extern FILE *profiler_output_file;\r
+extern unsigned int profiler_event_counter;\r
+#endif\r
+\r
+class ProcessWrapper : virtual public dol_sched_if, public sc_module\r
+{\r
+ public:\r
+ ProcessWrapper(sc_module_name name);\r
+ virtual ~ProcessWrapper();\r
+ virtual void initialize();\r
+ virtual int fire();\r
+ virtual bool isDetached() { return _isDetached; }\r
+ virtual void detach();\r
+ virtual int getIndex(unsigned indexNumber) const;\r
+ virtual char* getName() const;\r
+\r
+#ifdef INCLUDE_PROFILER\r
+ virtual void addToProfile(const char *event, void *port,\r
+ int length);\r
+#endif\r
+\r
+#ifdef INCLUDE_TRACE\r
+ int start_line;\r
+ int end_line;\r
+ char channel_name[NAME_LENGTH];\r
+#endif\r
+\r
+#ifdef INCLUDE_PERFORMANCE\r
+ int start_line;\r
+ int end_line;\r
+ CURRENT_TIME start_time;\r
+ CURRENT_TIME end_time;\r
+#endif\r
+\r
+ protected:\r
+ char* _name;\r
+ DOLProcess _process;\r
+ bool _isDetached;\r
+ int _iteratorIndex[4];\r
+ virtual int getIndex(const char* string, char* tokens,\r
+ int indexNumber) const;\r
+};\r
+\r
+#endif\r
+\r
--- /dev/null
+#include "WindowedFifo.h"\r
+\r
+/**\r
+ *\r
+ */\r
+WindowedFifo::WindowedFifo(char* name, unsigned size = 20) {\r
+ //std::cout << "Create WindowedFifo." << std::endl;\r
+ _size = size;\r
+ _buffer = new char[_size];\r
+ _head = 0;\r
+ _tail = 0;\r
+ _headRoom = 0;\r
+ _tailRoom = 0;\r
+ _use = 0;\r
+ //indicates whether Fifo is empty or full if _head == _tail\r
+ //_isFull = false;\r
+ _isHeadReserved = false;\r
+ _isTailReserved = false;\r
+ _name = new char[strlen(name) + 1];\r
+ strcpy(_name, name);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+WindowedFifo::~WindowedFifo() {\r
+ //std::cout << "Delete WindowedFifo." << std::endl;\r
+ if (_buffer) {\r
+ delete _buffer;\r
+ }\r
+ if (_name) {\r
+ delete _name;\r
+ }\r
+ _buffer = 0;\r
+ _head = 0;\r
+ _tail = 0;\r
+ _name = 0;\r
+ _use = 0;\r
+ //std::cout << "Deleted WindowedFifo." << std::endl;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::reserve(void** dest, unsigned len) {\r
+ char** destination = (char**)dest;\r
+ //std::cout << "Attempt to reserve " << len << " bytes." << std::endl;\r
+\r
+ //can only reserve once piece at a time\r
+ if (_isHeadReserved) {\r
+ *destination = 0;\r
+ return 0;\r
+ }\r
+\r
+ while (unused() == 0) {\r
+ wait(_readEvent);\r
+ }\r
+\r
+ //reserve at most as much memory as still available in the buffer\r
+ unsigned write = (len <= _size - _use ? len : _size - _use);\r
+\r
+ if (write > 0) {\r
+ //if wrap-around in buffer: return only buffer for the\r
+ //contiguous buffer space\r
+ if (_head + write > _size) {\r
+ write = _size - _head;\r
+ }\r
+\r
+ _headRoom = (_head + write) == _size? 0 : _head + write;\r
+ *destination = &(_buffer[_head]);\r
+ _isHeadReserved = true;\r
+\r
+ //the following comparison is unsafe in a multi-threaded\r
+ //environment and potentially leads to race-conditions\r
+ /*if (_headRoom == _tail) {\r
+ _isFull = true;\r
+ } else {\r
+ _isFull = false;\r
+ }*/\r
+ }\r
+\r
+ //std::cout << "Reserved " << write << " bytes." << std::endl;\r
+ _writeReserve = write; \r
+ return write;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void WindowedFifo::release() {\r
+ if (_isHeadReserved) {\r
+ //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl;\r
+ _head = _headRoom;\r
+ _use += _writeReserve;\r
+ _isHeadReserved = false;\r
+ _writeEvent.notify();\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::capture(void **dest, unsigned len) {\r
+ char** destination = (char**)dest;\r
+ //std::cout << "Attempt to capture " << len << " bytes." << std::endl;\r
+\r
+ if (_isTailReserved) {\r
+ //std::cout << "Only one attempt to capture allowed." << std::endl;\r
+ *destination = 0;\r
+ return 0;\r
+ }\r
+\r
+ while (used() == 0) {\r
+ wait(_writeEvent);\r
+ }\r
+\r
+ //capture at most as much data as available in the buffer\r
+ unsigned read = (len <= _use ? len : _use);\r
+\r
+ if ( read > 0 ) {\r
+ //if wrap-around in buffer: return only buffer for the\r
+ //contiguous buffer space\r
+ if (_tail + read> _size) {\r
+ read = _size - _tail;\r
+ }\r
+\r
+ _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read;\r
+ *destination = &(_buffer[_tail]);\r
+ _isTailReserved = true;\r
+ }\r
+\r
+ //std::cout << "Captured " << read << " bytes." << std::endl;\r
+\r
+ _readReserve = read; \r
+ return read;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void WindowedFifo::consume() {\r
+ if (_isTailReserved) {\r
+ //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl;\r
+ _tail = _tailRoom;\r
+ _use -= _readReserve;\r
+ _isTailReserved = false;\r
+ //_isFull = false;\r
+ _readEvent.notify();\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::size() const {\r
+ return _size;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::unused() const {\r
+ return _size - _use;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::used() const {\r
+ return _use;\r
+ /*if (_headRoom > _tail) {\r
+ return _headRoom - _tail;\r
+ } else if (_headRoom == _tail) {\r
+ if (_isFull == true) {\r
+ return _size;\r
+ } else {\r
+ return 0;\r
+ }\r
+ }\r
+ return _headRoom + _size - _tail;*/\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+char* WindowedFifo::getName() const {\r
+ return _name;\r
+}\r
+\r
+/**\r
+ * Test the implementation\r
+ */\r
+/*\r
+#include <iostream>\r
+#include <iomanip>\r
+#define LENGTH 10\r
+\r
+class producer : public sc_module\r
+{\r
+ public:\r
+ WindowedFifo *wfifo;\r
+\r
+ SC_HAS_PROCESS(producer);\r
+\r
+ producer(sc_module_name name) : sc_module(name)\r
+ {\r
+ SC_THREAD(main);\r
+ }\r
+\r
+ void main()\r
+ {\r
+ for (int j = 0; j < LENGTH; j++) {\r
+ //std::cout << "write " << i << " to Fifo. ";\r
+ int *buf1;\r
+ int write = wfifo->reserve((void**)&buf1, sizeof(int));\r
+\r
+ if (write == sizeof(int)) {\r
+ *buf1 = j;\r
+ wfifo->release();\r
+ //std::cout << "used: " << std::setw(2) << wfifo->used()\r
+ // << ", unused: " << std::setw(2) << wfifo->unused()\r
+ // << ", size: " << std::setw(2) << wfifo->size()\r
+ // << std::endl;\r
+ } else {\r
+ std::cout << "Not successful: " << write << std::endl;\r
+ }\r
+ }\r
+ printf("producer returns.\n");\r
+ }\r
+};\r
+\r
+class consumer : public sc_module\r
+{\r
+ public:\r
+ WindowedFifo *wfifo;\r
+\r
+ SC_HAS_PROCESS(consumer);\r
+\r
+ consumer(sc_module_name name) : sc_module(name)\r
+ {\r
+ SC_THREAD(main);\r
+ }\r
+\r
+ void main()\r
+ {\r
+ for (int j = 0; j < LENGTH; j++) {\r
+ int* buf3;\r
+ int read = wfifo->capture((void**)&buf3, sizeof(int));\r
+ if (read == sizeof(int)) {\r
+ std::cout << "read " << (unsigned)*buf3 << " from WindowedFifo ";\r
+ std::cout << "used: " << std::setw(2) << wfifo->used()\r
+ << ", unused: " << std::setw(2) << wfifo->unused()\r
+ << ", size: " << std::setw(2) << wfifo->size()\r
+ << std::endl;\r
+ wfifo->consume();\r
+ } else {\r
+ std::cout << "Read nothing from WindowedFifo." << std::endl;\r
+ }\r
+ }\r
+ printf("consumer returns.\n");\r
+ }\r
+};\r
+\r
+class top : public sc_module\r
+{\r
+ public:\r
+ WindowedFifo *wfifo_inst;\r
+ producer *prod_inst;\r
+ consumer *cons_inst;\r
+\r
+ top(sc_module_name name) : sc_module(name)\r
+ {\r
+ wfifo_inst = new WindowedFifo("myfifo", 4);\r
+\r
+ prod_inst = new producer("producer");\r
+ prod_inst->wfifo = wfifo_inst;\r
+\r
+ cons_inst = new consumer("consumer");\r
+ cons_inst->wfifo = wfifo_inst;\r
+ }\r
+};\r
+\r
+int sc_main (int argc , char *argv[]) {\r
+ top top1("top");\r
+ sc_start();\r
+ return 0;\r
+}\r
+*/\r
--- /dev/null
+#ifndef _WINDOWEDFIFO_H_\r
+#define _WINDOWEDFIFO_H_\r
+\r
+#include "systemc.h"\r
+\r
+class WindowedFifo {\r
+ public:\r
+ WindowedFifo(char* name, unsigned size);\r
+ virtual ~WindowedFifo();\r
+\r
+ virtual unsigned reserve(void** destination, unsigned len);\r
+ virtual void release();\r
+\r
+ virtual unsigned capture(void** destination, unsigned len);\r
+ virtual void consume();\r
+\r
+ virtual unsigned used() const;\r
+ virtual unsigned unused() const;\r
+ virtual unsigned size() const;\r
+ virtual char* getName() const;\r
+\r
+ protected:\r
+ char *_buffer;\r
+ unsigned _head;\r
+ unsigned _tail;\r
+ unsigned _headRoom;\r
+ unsigned _tailRoom;\r
+ unsigned _size;\r
+ unsigned _use;\r
+ unsigned _writeReserve;
+ unsigned _readReserve;
+ //bool _isFull;\r
+ bool _isHeadReserved;\r
+ bool _isTailReserved;\r
+ char *_name;\r
+ sc_event _readEvent;\r
+ sc_event _writeEvent;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#ifndef DOL_H
+#define DOL_H
+
+/************************************************************************
+ * do not add code to this header
+ ************************************************************************/
+
+/**
+ * Define the DOL process handler scheme.
+ * - Local variables are defined in structure LocalState. Local
+ * variables may vary from different processes.
+ * - The ProcessInit function pointer points to a function which
+ * initializes a process.
+ * - The ProcessFire function pointer points to a function which
+ * performs the actual computation. The communication between
+ * processes is inside the ProcessFire function.
+ * - The WPTR is a placeholder for callback. One can just
+ * leave it blank.
+ */
+
+//structure for local memory of process
+typedef struct _local_states *LocalState;
+
+//additional behavioral functions could be declared here
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+//process handler
+struct _process;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr; //placeholder for wrapper instance
+} DOLProcess;
+
+#endif
--- /dev/null
+#include "dolSupport.h"\r
+#include "ProcessWrapper.h"\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned write(void *port, void *buf, unsigned len, DOLProcess *process)\r
+{\r
+ Fifo *fifo = static_cast<Fifo *>(port);\r
+ char *str = static_cast<char*>(buf);\r
+ #ifdef INCLUDE_PROFILER\r
+ (static_cast<ProcessWrapper *>(process->wptr))->addToProfile(\r
+ "w", port, len);\r
+ #endif\r
+ fifo->write((void*)str, len);\r
+ #ifdef INCLUDE_TRACE\r
+ strcpy((static_cast<ProcessWrapper *>(process->wptr))->channel_name,\r
+ fifo->getName());\r
+ #endif\r
+ return len;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned read(void *port, void *buf, unsigned len, DOLProcess *process) {\r
+ Fifo *fifo = static_cast<Fifo *>(port);\r
+ char *str = static_cast<char*>(buf);\r
+ #ifdef INCLUDE_PROFILER\r
+ (static_cast<ProcessWrapper *>(process->wptr))->addToProfile(\r
+ "r", port, len);\r
+ #endif\r
+ fifo->read((void*)str, len);\r
+ #ifdef INCLUDE_TRACE\r
+ strcpy((static_cast<ProcessWrapper *>(process->wptr))->channel_name,\r
+ fifo->getName());\r
+ #endif\r
+ return len;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+int wtest(void *port, unsigned len, DOLProcess *process) {\r
+ Fifo *fifo = static_cast<Fifo *>(port);\r
+ return (fifo->unused() >= len) ? 1 : 0;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+int rtest(void *port, unsigned len, DOLProcess *process) {\r
+ Fifo *fifo = static_cast<Fifo *>(port);\r
+ return (fifo->used() >= len) ? 1 : 0;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned reserve(void* fifo, void** destination, unsigned len, DOLProcess* p) {\r
+ return ((WindowedFifo*)fifo)->reserve(destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void release(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*)fifo)->release();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned capture(void* fifo, void** destination, unsigned len, DOLProcess* p) {\r
+ return ((WindowedFifo*)fifo)->capture(destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void consume(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*)fifo)->consume();\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void DOL_detach(DOLProcess* p) {\r
+ static_cast<ProcessWrapper *>(p->wptr)->detach();\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0) {\r
+ *port = (void**)((void**)base)[index0];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1) {\r
+ *port = (void**)((void**)base)[index0 * range1 + index1];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2) {\r
+ *port = (void**)((void**)base)[index0 * range1 * range2\r
+ + index1 * range2 + index2];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2,\r
+ int index3, int range3) {\r
+ *port = (void**)((void**)base)[index0 * range1 * range2 * range3\r
+ + index1 * range2 * range3\r
+ + index2 * range3\r
+ + index3];\r
+}\r
--- /dev/null
+#ifndef DOLSUPPORT_H\r
+#define DOLSUPPORT_H\r
+\r
+#include "dol.h"\r
+#include "Fifo.h"\r
+#include "functional_trace.h"\r
+#include "Performance_Extraction.h"\r
+\r
+#ifdef INCLUDE_PERFORMANCE\r
+#define DOL_write(port, buf, len, process) {\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line = __LINE__;\\r
+ get_current_time(&((static_cast<ProcessWrapper *>(p->wptr))->\\r
+ end_time));\\r
+ performance_extraction.add_computation_performance(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(),\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line,\\r
+ &((static_cast<ProcessWrapper *>(p->wptr))->start_time),\\r
+ &((static_cast<ProcessWrapper *>(p->wptr))->end_time));\\r
+ write(port, buf, len, process);\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line = __LINE__;\\r
+ get_current_time(&((static_cast<ProcessWrapper *>(p->wptr))->\\r
+ start_time)); }\r
+#define DOL_read(port, buf, len, process) {\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line = __LINE__;\\r
+ get_current_time(&((static_cast<ProcessWrapper *>(p->wptr))->\\r
+ end_time));\\r
+ performance_extraction.add_computation_performance(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(),\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line,\\r
+ &((static_cast<ProcessWrapper *>(p->wptr))->start_time),\\r
+ &((static_cast<ProcessWrapper *>(p->wptr))->end_time));\\r
+ read(port, buf, len, process);\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line = __LINE__;\\r
+ get_current_time(&((static_cast<ProcessWrapper *>(p->wptr))->\\r
+ start_time)); }\r
+#elif INCLUDE_TRACE\r
+#define DOL_write(port, buf, len, process) {\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line = __LINE__;\\r
+ dol_functional_trace.create_computation_event(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(),\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line);\\r
+ write(port, buf, len, process);\\r
+ dol_functional_trace.create_write_event(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(), len,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->channel_name);\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line = __LINE__; }\r
+#define DOL_read(port, buf, len, process) {\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line = __LINE__;\\r
+ dol_functional_trace.create_computation_event(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(),\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->end_line);\\r
+ read(port, buf, len, process);\\r
+ dol_functional_trace.create_read_event(\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->basename(), len,\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->channel_name);\\r
+ (static_cast<ProcessWrapper *>(p->wptr))->start_line = __LINE__; }\r
+#else\r
+ #define DOL_write(port, buf, len, process) \\r
+ write(port, buf, len, process)\r
+ #define DOL_read(port, buf, len, process) \\r
+ read(port, buf, len, process)\r
+#endif\r
+\r
+#define DOL_reserve(port, buf, size, process) \\r
+ reserve(port, (void**)buf, size, process);\r
+\r
+#define DOL_release(port, process) \\r
+ release(port, process);\r
+\r
+#define DOL_capture(port, buf, size, process) \\r
+ capture(port, (void**)buf, size, process);\r
+\r
+#define DOL_consume(port, process) \\r
+ consume(port, process);\r
+\r
+#define DOL_wtest(port, len, process) wtest(port, len, process)\r
+\r
+#define DOL_rtest(port, len, process) rtest(port, len, process)\r
+\r
+void DOL_detach(DOLProcess* p);\r
+\r
+//fifo access functions\r
+unsigned write(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+unsigned read(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+int wtest(void *port, unsigned len, DOLProcess *process);\r
+int rtest(void *port, unsigned len, DOLProcess *process);\r
+\r
+//windowed fifo access functions\r
+unsigned reserve(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+void release(void* fifo, DOLProcess* p);\r
+unsigned capture(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+void consume(void* fifo, DOLProcess* p);\r
+\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2,\r
+ int index3, int range3);\r
+\r
+#define GETINDEX(dimension) \\r
+ static_cast<ProcessWrapper *>(p->wptr)->getIndex(dimension)\r
+\r
+/**\r
+ * macro to create a variable to store a port name\r
+ *\r
+ * @param name name of the variable\r
+ */\r
+#define CREATEPORTVAR(name) Fifo *name\r
+\r
+/**\r
+ * Create the port name of an iterated port based on its basename and the\r
+ * given indices.\r
+ *\r
+ * @param port buffer where the result is stored (created using\r
+ * CREATEPORTVAR)\r
+ * @param base basename of the port\r
+ * @param number_of_indices number of dimensions of the port\r
+ * @param index_range_pairs index and range values for each dimension\r
+ */\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+ createPort((void**)(&port), base, number_of_indices, index_range_pairs)\r
+\r
+#endif\r
--- /dev/null
+/**************************************************************************\r
+ dol_sched_if.h\r
+ \r
+ Scheduler interface for a DOL process \r
+\r
+ (c) 2006 by Alexander Maxiaguine <maxiagui@tik.ee.ethz.ch>\r
+\r
+ Computer Engineering and Networks Laboratory, TIK\r
+ Swiss Federal Institute of Technology, ETHZ Zurich \r
+ Switzerland\r
+\r
+**************************************************************************/\r
+\r
+/**************************************************************************\r
+ Change Log:\r
+\r
+ 14.03.06 -- creation\r
+\r
+**************************************************************************/\r
+\r
+#ifndef DOL_SCHED_IF_H\r
+#define DOL_SCHED_IF_H\r
+\r
+class dol_sched_if \r
+{\r
+\r
+public:\r
+ virtual void initialize() = 0;\r
+ virtual int fire() = 0;\r
+\r
+\r
+protected:\r
+ dol_sched_if() {}\r
+\r
+\r
+private:\r
+\r
+ // disabled\r
+ dol_sched_if( const dol_sched_if& );\r
+ dol_sched_if& operator = ( const dol_sched_if& );\r
+};\r
+\r
+#endif\r
--- /dev/null
+#include "functional_trace.h"\r
+\r
+functional_trace dol_functional_trace;\r
+\r
+functional_trace::functional_trace()\r
+{\r
+ //DBGPRINT;\r
+ strcpy(trace_file_name, "trace1.txt");\r
+ event_num = 0;\r
+ file_index = 1;\r
+}\r
+\r
+functional_trace::~functional_trace()\r
+{\r
+ //DBGPRINT;\r
+ char temp[NAME_LENGTH];\r
+#ifdef INCLUDE_TRACE\r
+ strcpy(trace_file_name, "trace");\r
+ sprintf(temp, "%d", file_index);\r
+ strcat(trace_file_name, temp);\r
+ strcat(trace_file_name, ".txt");\r
+ write_to_file(trace_file_name);\r
+ free_traces();\r
+ //printf("The traces in the memory have been freed\n");\r
+#endif\r
+ //DBGPRINT;\r
+}\r
+\r
+void functional_trace::add_event_node(TRACE_EVENT &trace_event)\r
+{\r
+ Process_Trace *process_trace_ptr;\r
+ char temp[NAME_LENGTH];\r
+\r
+ process_trace_ptr = get_process_trace(trace_event.process_name);\r
+ if (process_trace_ptr == NULL)\r
+ {\r
+ process_trace_ptr = new Process_Trace(trace_event.process_name);\r
+ _list_process_trace.push_back(process_trace_ptr);\r
+ }\r
+\r
+ process_trace_ptr->add_entry(&trace_event);\r
+\r
+ event_num++;\r
+ if (event_num > 8000000)\r
+ {\r
+ strcpy(trace_file_name, "trace");\r
+ sprintf(temp, "%d", file_index);\r
+ strcat(trace_file_name, temp);\r
+ strcat(trace_file_name, ".txt");\r
+ write_to_file(trace_file_name);\r
+ free_traces();\r
+ file_index++;\r
+ event_num = 0;\r
+ }\r
+\r
+}\r
+\r
+/*\r
+void functional_trace::add_event_node(TRACE_EVENT &trace_event)\r
+{\r
+ XMLNode process_node;\r
+ char temp[NAME_LENGTH];\r
+ process_node = xml_main_node.getChildNode(trace_event.process_name);\r
+\r
+ if(process_node.isEmpty())\r
+ {\r
+ process_node = xml_main_node.addChild(trace_event.process_name);\r
+ }\r
+\r
+ XMLNode event_node = process_node.addChild("event");\r
+\r
+ event_node.addAttribute("type", trace_event_type_string[trace_event.event_type]);\r
+\r
+ if(trace_event.event_type == COMPUTATION_EVENT)\r
+ {\r
+\r
+ sprintf(temp, "%d", trace_event.computation_start_line);\r
+ event_node.addAttribute("start", temp);\r
+ sprintf(temp, "%d", trace_event.computation_end_line);\r
+ event_node.addAttribute("end", temp);\r
+ }\r
+ else if((trace_event.event_type == READ_EVENT) || (trace_event.event_type == WRITE_EVENT))\r
+ {\r
+ sprintf(temp, "%d", trace_event.data_num);\r
+ event_node.addAttribute("data_num", temp);\r
+ event_node.addAttribute("channel_name", trace_event.channel_name);\r
+ }\r
+}\r
+*/\r
+\r
+void functional_trace::create_computation_event(const char *process_name, int start_line, int end_line)\r
+{\r
+ TRACE_EVENT trace_event;\r
+\r
+ trace_event.event_type = COMPUTATION_EVENT;\r
+ strcpy(trace_event.process_name, process_name);\r
+ trace_event.computation_start_line = start_line;\r
+ trace_event.computation_end_line = end_line;\r
+ strcpy(trace_event.channel_name, "");\r
+ trace_event.data_num = 0;\r
+\r
+ add_event_node(trace_event);\r
+}\r
+\r
+void functional_trace::create_read_event(const char *process_name, int data_num, const char *channel_name)\r
+{\r
+ //DBGPRINT;\r
+ TRACE_EVENT trace_event;\r
+ trace_event.event_type = READ_EVENT;\r
+ strcpy(trace_event.process_name, process_name);\r
+ trace_event.data_num = data_num;\r
+ strcpy(trace_event.channel_name, channel_name);\r
+\r
+ trace_event.computation_start_line = 0;\r
+ trace_event.computation_end_line = 0;\r
+\r
+ add_event_node(trace_event);\r
+}\r
+\r
+void functional_trace::create_write_event(const char *process_name, int data_num, const char *channel_name)\r
+{\r
+ //DBGPRINT;\r
+ TRACE_EVENT trace_event;\r
+ trace_event.event_type = WRITE_EVENT;\r
+ strcpy(trace_event.process_name, process_name);\r
+ trace_event.data_num = data_num;\r
+ strcpy(trace_event.channel_name, channel_name);\r
+\r
+ trace_event.computation_start_line = 0;\r
+ trace_event.computation_end_line = 0;\r
+\r
+ add_event_node(trace_event);\r
+}\r
+\r
+\r
+Process_Trace *functional_trace::get_process_trace(const char *process_name)\r
+{\r
+ Process_Trace *process_trace_ptr;\r
+\r
+ for (_iter_process_trace = _list_process_trace.begin();\r
+ _iter_process_trace != _list_process_trace.end();\r
+ _iter_process_trace++)\r
+ {\r
+ process_trace_ptr = *_iter_process_trace;\r
+\r
+ if (strcmp(process_trace_ptr->get_name(), process_name) == 0)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (_iter_process_trace == _list_process_trace.end())\r
+ {\r
+ process_trace_ptr = NULL;\r
+ }\r
+\r
+ return process_trace_ptr;\r
+}\r
+\r
+void functional_trace::free_traces()\r
+{\r
+ Process_Trace *process_trace_ptr;\r
+\r
+ for (_iter_process_trace = _list_process_trace.begin();\r
+ _iter_process_trace != _list_process_trace.end();\r
+ _iter_process_trace++)\r
+ {\r
+ process_trace_ptr = *_iter_process_trace;\r
+ delete process_trace_ptr;\r
+ }\r
+ _list_process_trace.clear();\r
+}\r
+\r
+int functional_trace::write_to_file(const char *trace_file_name) {\r
+ int ret = -1;\r
+ Process_Trace *process_trace_ptr;\r
+ FILE *trace_file_handle;\r
+ EVENT_ENTRY *event_entry_ptr;\r
+\r
+ if ((trace_file_handle = fopen(trace_file_name, "w")) == NULL) {\r
+ ret = -1;\r
+ printf("Can not create file: %s\n", trace_file_name);\r
+ goto end1;\r
+ }\r
+\r
+ for (_iter_process_trace = _list_process_trace.begin();\r
+ _iter_process_trace != _list_process_trace.end();\r
+ _iter_process_trace++) {\r
+ process_trace_ptr = *_iter_process_trace;\r
+ fprintf(trace_file_handle, "$ %s\n", process_trace_ptr->get_name());\r
+\r
+ event_entry_ptr = process_trace_ptr->get_head_entry();\r
+ while (event_entry_ptr != NULL) {\r
+ if (event_entry_ptr->event_type == COMPUTATION_EVENT) {\r
+ if (event_entry_ptr->end_line!=(event_entry_ptr->start_line+1))\r
+ fprintf(trace_file_handle, "c %d %d\n",\r
+ event_entry_ptr->start_line,\r
+ event_entry_ptr->end_line);\r
+ }\r
+ else if (event_entry_ptr->event_type == WRITE_EVENT) {\r
+ fprintf(trace_file_handle, "w %d %s\n",\r
+ event_entry_ptr->data_num,\r
+ event_entry_ptr->channel_name);\r
+ }\r
+ else if (event_entry_ptr->event_type == READ_EVENT) {\r
+ fprintf(trace_file_handle, "r %d %s\n",\r
+ event_entry_ptr->data_num,\r
+ event_entry_ptr->channel_name);\r
+ }\r
+\r
+ event_entry_ptr = event_entry_ptr->next;\r
+ }\r
+ }\r
+\r
+ fflush(trace_file_handle);\r
+ fseek(trace_file_handle, 0, SEEK_SET);\r
+ fclose(trace_file_handle);\r
+\r
+end1:\r
+ return ret;\r
+}\r
+\r
+Process_Trace::Process_Trace(const char *process_name)\r
+{\r
+ strcpy(_process_name, process_name);\r
+ _head = NULL;\r
+ _tail = NULL;\r
+}\r
+\r
+Process_Trace::~Process_Trace()\r
+{\r
+ EVENT_ENTRY *temp;\r
+\r
+ while (_head != NULL)\r
+ {\r
+ temp = _head;\r
+ _head = _head->next;\r
+ if (temp->channel_name != NULL)\r
+ delete [] temp->channel_name;\r
+ delete temp;\r
+ }\r
+}\r
+\r
+const char *Process_Trace::get_name()\r
+{\r
+ return _process_name;\r
+}\r
+\r
+EVENT_ENTRY *Process_Trace::get_head_entry()\r
+{\r
+ return _head;\r
+}\r
+\r
+int Process_Trace::add_entry(TRACE_EVENT *trace_event_ptr)\r
+{\r
+ int ret = 0;\r
+ EVENT_ENTRY *temp;\r
+ int channel_name_length;\r
+\r
+ temp = new EVENT_ENTRY;\r
+ memset(temp, 0, sizeof(EVENT_ENTRY));\r
+\r
+ temp->event_type = trace_event_ptr->event_type;\r
+ temp->start_line = trace_event_ptr->computation_start_line;\r
+ temp->end_line = trace_event_ptr->computation_end_line;\r
+ temp->data_num = trace_event_ptr->data_num;\r
+\r
+ channel_name_length = strlen(trace_event_ptr->channel_name);\r
+ if (channel_name_length != 0)\r
+ {\r
+ temp->channel_name = new char[channel_name_length + 1];\r
+ strcpy(temp->channel_name, trace_event_ptr->channel_name);\r
+ }\r
+ else\r
+ {\r
+ temp->channel_name = NULL;\r
+ }\r
+\r
+ if (_head == NULL)\r
+ {\r
+ _head = temp;\r
+ _tail = temp;\r
+ temp->next = NULL;\r
+ }\r
+ else\r
+ {\r
+ _tail->next = temp;\r
+ _tail = temp;\r
+ temp->next = NULL;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
--- /dev/null
+#ifndef _FUNCTIONAL_H\r
+#define _FUNCTIONAL_H\r
+\r
+#include "trace.h"\r
+\r
+typedef struct EVENT_ENTRY\r
+{\r
+ char event_type;\r
+ int start_line;\r
+ int end_line;\r
+ int data_num;\r
+ char *channel_name;\r
+\r
+ EVENT_ENTRY *next;\r
+}EVENT_ENTRY;\r
+\r
+class Process_Trace\r
+{\r
+private:\r
+ char _process_name[NAME_LENGTH];\r
+ EVENT_ENTRY *_head;\r
+ EVENT_ENTRY *_tail;\r
+\r
+public:\r
+ Process_Trace(const char *process_name);\r
+ ~Process_Trace();\r
+\r
+ const char *get_name();\r
+ int add_entry(TRACE_EVENT *trace_event_ptr);\r
+ EVENT_ENTRY *get_head_entry();\r
+};\r
+\r
+class functional_trace\r
+{\r
+public:\r
+ char trace_file_name[NAME_LENGTH];\r
+ unsigned long event_num;\r
+ int file_index;\r
+\r
+ list<Process_Trace *> _list_process_trace;\r
+ list<Process_Trace *>::iterator _iter_process_trace;\r
+\r
+ functional_trace();\r
+ ~functional_trace();\r
+\r
+ void add_event_node(TRACE_EVENT &trace_event);\r
+ void create_computation_event(const char *process_name, int start_line, int end_line);\r
+ void create_read_event(const char *process_name, int data_num, const char *channel_name);\r
+ void create_write_event(const char *process_name, int data_num, const char *channel_name);\r
+ int write_to_file(const char *trace_file_name);\r
+ Process_Trace *get_process_trace(const char *process_name);\r
+ void free_traces();\r
+};\r
+\r
+extern functional_trace dol_functional_trace;\r
+\r
+#endif\r
--- /dev/null
+#ifndef _TRACE_H\r
+#define _TRACE_H\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include "xmlParser.h"\r
+#include <list>\r
+\r
+using namespace std;\r
+\r
+#define NAME_LENGTH 256\r
+#ifdef DBG\r
+#define DBGPRINT printf("file: %s--line: %d\n", __FILE__, __LINE__)\r
+#else\r
+#define DBGPRINT\r
+#endif\r
+\r
+typedef enum TRACE_EVENT_TYPE\r
+{\r
+ COMPUTATION_EVENT,\r
+ READ_EVENT,\r
+ WRITE_EVENT,\r
+ UNKOWN\r
+}TRACE_EVENT_TYPE;\r
+\r
+#define MAX_EVENT_TYPE 3\r
+\r
+typedef struct TRACE_EVENT\r
+{\r
+ char process_name[NAME_LENGTH];\r
+ char event_type;\r
+ int computation_start_line;\r
+ int computation_end_line;\r
+ int data_num;\r
+ char channel_name[NAME_LENGTH];\r
+}TRACE_EVENT;\r
+\r
+#endif\r
--- /dev/null
+/**
+ ****************************************************************************
+ * <P> XML.c - implementation file for basic XML parser written in ANSI C++
+ * for portability. It works by using recursion and a node tree for breaking
+ * down the elements of an XML document. </P>
+ *
+ * @version V2.23
+ * @author Frank Vanden Berghen
+ *
+ * NOTE:
+ *
+ * If you add "#define STRICT_PARSING", on the first line of this file
+ * the parser will see the following XML-stream:
+ * <a><b>some text</b><b>other text </a>
+ * as an error. Otherwise, this tring will be equivalent to:
+ * <a><b>some text</b><b>other text</b></a>
+ *
+ * NOTE:
+ *
+ * If you add "#define APPROXIMATE_PARSING" on the first line of this file
+ * the parser will see the following XML-stream:
+ * <data name="n1">
+ * <data name="n2">
+ * <data name="n3" />
+ * as equivalent to the following XML-stream:
+ * <data name="n1" />
+ * <data name="n2" />
+ * <data name="n3" />
+ * This can be useful for badly-formed XML-streams but prevent the use
+ * of the following XML-stream (problem is: tags at contiguous levels
+ * have the same names):
+ * <data name="n1">
+ * <data name="n2">
+ * <data name="n3" />
+ * </data>
+ * </data>
+ *
+ * NOTE:
+ *
+ * If you add "#define _XMLPARSER_NO_MESSAGEBOX_" on the first line of this file
+ * the "openFileHelper" function will always display error messages inside the
+ * console instead of inside a message-box-window. Message-box-windows are
+ * available on windows 9x/NT/2000/XP/Vista only.
+ *
+ * BSD license:
+ * Copyright (c) 2002, Frank Vanden Berghen
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Frank Vanden Berghen nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************
+ */
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+#include "xmlParser.h"
+#ifdef _XMLWINDOWS
+//#ifdef _DEBUG
+//#define _CRTDBG_MAP_ALLOC
+//#include <crtdbg.h>
+//#endif
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h> // to have IsTextUnicode, MultiByteToWideChar, WideCharToMultiByte to handle unicode files
+ // to have "MessageBoxA" to display error messages for openFilHelper
+#endif
+
+#include <memory.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+XMLCSTR XMLNode::getVersion() { return _T("v2.23"); }
+void free_XMLDLL(void *t){free(t);}
+
+static char strictUTF8Parsing=1, guessUnicodeChars=1, dropWhiteSpace=1;
+
+inline int mmin( const int t1, const int t2 ) { return t1 < t2 ? t1 : t2; }
+
+// You can modify the initialization of the variable "XMLClearTags" below
+// to change the clearTags that are currently recognized by the library.
+// The number on the second columns is the length of the string inside the
+// first column. The "<!DOCTYPE" declaration must be the second in the list.
+static ALLXMLClearTag XMLClearTags[] =
+{
+ { _T("<![CDATA["),9, _T("]]>") },
+ { _T("<!DOCTYPE"),9, _T(">") },
+ { _T("<PRE>") ,5, _T("</PRE>") },
+ { _T("<Script>") ,8, _T("</Script>")},
+ { _T("<!--") ,4, _T("-->") },
+ { NULL ,0, NULL }
+};
+ALLXMLClearTag* XMLNode::getClearTagTable() { return XMLClearTags; }
+
+// You can modify the initialization of the variable "XMLEntities" below
+// to change the character entities that are currently recognized by the library.
+// The number on the second columns is the length of the string inside the
+// first column. Additionally, the syntaxes " " and " " are recognized.
+typedef struct { XMLCSTR s; int l; XMLCHAR c;} XMLCharacterEntity;
+static XMLCharacterEntity XMLEntities[] =
+{
+ { _T("&" ), 5, _T('&' )},
+ { _T("<" ), 4, _T('<' )},
+ { _T(">" ), 4, _T('>' )},
+ { _T("""), 6, _T('\"')},
+ { _T("'"), 6, _T('\'')},
+ { NULL , 0, '\0' }
+};
+
+// When rendering the XMLNode to a string (using the "createXMLString" function),
+// you can ask for a beautiful formatting. This formatting is using the
+// following indentation character:
+#define INDENTCHAR _T('\t')
+
+// The following function parses the XML errors into a user friendly string.
+// You can edit this to change the output language of the library to something else.
+XMLCSTR XMLNode::getError(XMLError xerror)
+{
+ switch (xerror)
+ {
+ case eXMLErrorNone: return _T("No error");
+ case eXMLErrorMissingEndTag: return _T("Warning: Unmatched end tag");
+ case eXMLErrorEmpty: return _T("Error: No XML data");
+ case eXMLErrorFirstNotStartTag: return _T("Error: First token not start tag");
+ case eXMLErrorMissingTagName: return _T("Error: Missing start tag name");
+ case eXMLErrorMissingEndTagName: return _T("Error: Missing end tag name");
+ case eXMLErrorNoMatchingQuote: return _T("Error: Unmatched quote");
+ case eXMLErrorUnmatchedEndTag: return _T("Error: Unmatched end tag");
+ case eXMLErrorUnmatchedEndClearTag: return _T("Error: Unmatched clear tag end");
+ case eXMLErrorUnexpectedToken: return _T("Error: Unexpected token found");
+ case eXMLErrorInvalidTag: return _T("Error: Invalid tag found");
+ case eXMLErrorNoElements: return _T("Error: No elements found");
+ case eXMLErrorFileNotFound: return _T("Error: File not found");
+ case eXMLErrorFirstTagNotFound: return _T("Error: First Tag not found");
+ case eXMLErrorUnknownCharacterEntity:return _T("Error: Unknown character entity");
+ case eXMLErrorCharConversionError: return _T("Error: unable to convert between UNICODE and MultiByte chars");
+ case eXMLErrorCannotOpenWriteFile: return _T("Error: unable to open file for writing");
+ case eXMLErrorCannotWriteFile: return _T("Error: cannot write into file");
+
+ case eXMLErrorBase64DataSizeIsNotMultipleOf4: return _T("Warning: Base64-string length is not a multiple of 4");
+ case eXMLErrorBase64DecodeTruncatedData: return _T("Warning: Base64-string is truncated");
+ case eXMLErrorBase64DecodeIllegalCharacter: return _T("Error: Base64-string contains an illegal character");
+ case eXMLErrorBase64DecodeBufferTooSmall: return _T("Error: Base64 decode output buffer is too small");
+ };
+ return _T("Unknown");
+}
+
+// Here is an abstraction layer to access some common string manipulation functions.
+// The abstraction layer is currently working for gcc, Microsoft Visual Studio 6.0,
+// Microsoft Visual Studio .NET, CC (sun compiler) and Borland C++.
+// If you plan to "port" the library to a new system/compiler, all you have to do is
+// to edit the following lines.
+#ifdef XML_NO_WIDE_CHAR
+char myIsTextUnicode(const void *b, int len) { return FALSE; }
+#else
+ #if defined (UNDER_CE) || !defined(WIN32)
+ char myIsTextUnicode(const void *b, int len) // inspired by the Wine API: RtlIsTextUnicode
+ {
+#ifdef sun
+ // for SPARC processors: wchar_t* buffers must always be alligned, otherwise it's a char* buffer.
+ if ((((unsigned long)b)%sizeof(wchar_t))!=0) return FALSE;
+#endif
+ const wchar_t *s=(const wchar_t*)b;
+
+ // buffer too small:
+ if (len<(int)sizeof(wchar_t)) return FALSE;
+
+ // odd length test
+ if (len&1) return FALSE;
+
+ /* only checks the first 256 characters */
+ len=mmin(256,len/sizeof(wchar_t));
+
+ // Check for the special byte order:
+ if (*s == 0xFFFE) return FALSE; // IS_TEXT_UNICODE_REVERSE_SIGNATURE;
+ if (*s == 0xFEFF) return TRUE; // IS_TEXT_UNICODE_SIGNATURE
+
+ // checks for ASCII characters in the UNICODE stream
+ int i,stats=0;
+ for (i=0; i<len; i++) if (s[i]<=(unsigned short)255) stats++;
+ if (stats>len/2) return TRUE;
+
+ // Check for UNICODE NULL chars
+ for (i=0; i<len; i++) if (!s[i]) return TRUE;
+
+ return FALSE;
+ }
+ #else
+ char myIsTextUnicode(const void *b,int l) { return (char)IsTextUnicode((CONST LPVOID)b,l,NULL); };
+ #endif
+#endif
+
+#ifdef _XMLWINDOWS
+// for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET,
+ #ifdef _XMLUNICODE
+ wchar_t *myMultiByteToWideChar(const char *s,int l)
+ {
+ int i;
+ if (strictUTF8Parsing) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,l,NULL,0);
+ else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,l,NULL,0);
+ if (i<0) return NULL;
+ wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(XMLCHAR));
+ if (strictUTF8Parsing) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,l,d,i);
+ else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,l,d,i);
+ d[i]=0;
+ return d;
+ }
+ #else
+ char *myWideCharToMultiByte(const wchar_t *s,int l)
+ {
+ UINT codePage=CP_ACP; if (strictUTF8Parsing) codePage=CP_UTF8;
+ int i=(int)WideCharToMultiByte(codePage, // code page
+ 0, // performance and mapping flags
+ s, // wide-character string
+ l, // number of chars in string
+ NULL, // buffer for new string
+ 0, // size of buffer
+ NULL, // default for unmappable chars
+ NULL // set when default char used
+ );
+ if (i<0) return NULL;
+ char *d=(char*)malloc(i+1);
+ WideCharToMultiByte(codePage, // code page
+ 0, // performance and mapping flags
+ s, // wide-character string
+ l, // number of chars in string
+ d, // buffer for new string
+ i, // size of buffer
+ NULL, // default for unmappable chars
+ NULL // set when default char used
+ );
+ d[i]=0;
+ return d;
+ }
+ #endif
+ #ifdef __BORLANDC__
+ int _strnicmp(char *c1, char *c2, int l){ return strnicmp(c1,c2,l);}
+ #endif
+#else
+// for gcc and CC
+ #ifdef XML_NO_WIDE_CHAR
+ char *myWideCharToMultiByte(const wchar_t *s, int l) { return NULL; }
+ #else
+ char *myWideCharToMultiByte(const wchar_t *s, int l)
+ {
+ const wchar_t *ss=s;
+ int i=(int)wcsrtombs(NULL,&ss,0,NULL);
+ if (i<0) return NULL;
+ char *d=(char *)malloc(i+1);
+ wcsrtombs(d,&s,i,NULL);
+ d[i]=0;
+ return d;
+ }
+ #endif
+ #ifdef _XMLUNICODE
+ wchar_t *myMultiByteToWideChar(const char *s, int l)
+ {
+ const char *ss=s;
+ int i=(int)mbsrtowcs(NULL,&ss,0,NULL);
+ if (i<0) return NULL;
+ wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(wchar_t));
+ mbsrtowcs(d,&s,l,NULL);
+ d[i]=0;
+ return d;
+ }
+ int _tcslen(XMLCSTR c) { return wcslen(c); }
+ #ifdef sun
+ // for CC
+ #include <widec.h>
+ int _tcsnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncasecmp(c1,c2,l);}
+ int _tcsicmp(XMLCSTR c1, XMLCSTR c2) { return wscasecmp(c1,c2); }
+ #else
+ // for gcc
+ int _tcsnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncasecmp(c1,c2,l);}
+ int _tcsicmp(XMLCSTR c1, XMLCSTR c2) { return wcscasecmp(c1,c2); }
+ #endif
+ XMLSTR _tcsstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)wcsstr(c1,c2); }
+ XMLSTR _tcscpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)wcscpy(c1,c2); }
+ FILE *_tfopen(XMLCSTR filename,XMLCSTR mode)
+ {
+ char *filenameAscii=myWideCharToMultiByte(filename,0);
+ FILE *f;
+ if (mode[0]==_T('r')) f=fopen(filenameAscii,"rb");
+ else f=fopen(filenameAscii,"wb");
+ free(filenameAscii);
+ return f;
+ }
+ #else
+ FILE *_tfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); }
+ int _tcslen(XMLCSTR c) { return strlen(c); }
+ int _tcsnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncasecmp(c1,c2,l);}
+ int _tcsicmp(XMLCSTR c1, XMLCSTR c2) { return strcasecmp(c1,c2); }
+ XMLSTR _tcsstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)strstr(c1,c2); }
+ XMLSTR _tcscpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)strcpy(c1,c2); }
+ #endif
+ int _strnicmp(const char *c1,const char *c2, int l) { return strncasecmp(c1,c2,l);}
+#endif
+
+/////////////////////////////////////////////////////////////////////////
+// Here start the core implementation of the XMLParser library //
+/////////////////////////////////////////////////////////////////////////
+
+// You should normally not change anything below this point.
+// For your own information, I suggest that you read the openFileHelper below:
+XMLNode XMLNode::openFileHelper(XMLCSTR filename, XMLCSTR tag)
+{
+ // guess the value of the global parameter "strictUTF8Parsing"
+ // (the guess is based on the first 200 bytes of the file).
+ FILE *f=_tfopen(filename,_T("rb"));
+ if (f)
+ {
+ char bb[205];
+ int l=(int)fread(bb,1,200,f);
+ setGlobalOptions(guessUnicodeChars,guessUTF8ParsingParameterValue(bb,l),dropWhiteSpace);
+ fclose(f);
+ }
+
+ // parse the file
+ XMLResults pResults;
+ XMLNode xnode=XMLNode::parseFile(filename,tag,&pResults);
+
+ // display error message (if any)
+ if (pResults.error != eXMLErrorNone)
+ {
+ // create message
+ char message[2000],*s1=(char*)"",*s3=(char*)""; XMLCSTR s2=_T("");
+ if (pResults.error==eXMLErrorFirstTagNotFound) { s1=(char*)"First Tag should be '"; s2=tag; s3=(char*)"'.\n"; }
+ sprintf(message,
+#ifdef _XMLUNICODE
+ "XML Parsing error inside file '%S'.\n%S\nAt line %i, column %i.\n%s%S%s"
+#else
+ "XML Parsing error inside file '%s'.\n%s\nAt line %i, column %i.\n%s%s%s"
+#endif
+ ,filename,XMLNode::getError(pResults.error),pResults.nLine,pResults.nColumn,s1,s2,s3);
+
+ // display message
+#if defined(WIN32) && !defined(UNDER_CE) && !defined(_XMLPARSER_NO_MESSAGEBOX_)
+ MessageBoxA(NULL,message,"XML Parsing error",MB_OK|MB_ICONERROR|MB_TOPMOST);
+#else
+ printf("%s",message);
+#endif
+ exit(255);
+ }
+ return xnode;
+}
+
+#ifndef _XMLUNICODE
+// If "strictUTF8Parsing=0" then we assume that all characters have the same length of 1 byte.
+// If "strictUTF8Parsing=1" then the characters have different lengths (from 1 byte to 4 bytes).
+// This table is used as lookup-table to know the length of a character (in byte) based on the
+// content of the first byte of the character.
+// (note: if you modify this, you must always have XML_utf8ByteTable[0]=0 ).
+static const char XML_utf8ByteTable[256] =
+{
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70End of ASCII range
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x80 0x80 to 0xc1 invalid
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x90
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0
+ 1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0 0xc2 to 0xdf 2 byte
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,// 0xe0 0xe0 to 0xef 3 byte
+ 4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
+};
+static const char XML_asciiByteTable[256] =
+{
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+static const char *XML_ByteTable=(const char *)XML_utf8ByteTable; // the default is "strictUTF8Parsing=1"
+#endif
+
+XMLError XMLNode::writeToFile(XMLCSTR filename, const char *encoding, char nFormat) const
+{
+ int i;
+ XMLSTR t=createXMLString(nFormat,&i);
+ FILE *f=_tfopen(filename,_T("wb"));
+ if (!f) return eXMLErrorCannotOpenWriteFile;
+#ifdef _XMLUNICODE
+ unsigned char h[2]={ 0xFF, 0xFE };
+ if (!fwrite(h,2,1,f)) return eXMLErrorCannotWriteFile;
+ if (!isDeclaration())
+ {
+ if (!fwrite(_T("<?xml version=\"1.0\" encoding=\"utf-16\"?>\n"),sizeof(wchar_t)*40,1,f))
+ return eXMLErrorCannotWriteFile;
+ }
+#else
+ if (!isDeclaration())
+ {
+ if ((!encoding)||(XML_ByteTable==XML_utf8ByteTable))
+ {
+ // header so that windows recognize the file as UTF-8:
+// unsigned char h[3]={0xEF,0xBB,0xBF};
+// if (!fwrite(h,3,1,f)) return eXMLErrorCannotWriteFile;
+ if (!fwrite("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",39,1,f)) return eXMLErrorCannotWriteFile;
+ }
+ else
+ if (fprintf(f,"<?xml version=\"1.0\" encoding=\"%s\"?>\n",encoding)<0) return eXMLErrorCannotWriteFile;
+ } else
+ {
+ if (XML_ByteTable==XML_utf8ByteTable) // test if strictUTF8Parsing==1"
+ {
+// unsigned char h[3]={0xEF,0xBB,0xBF}; if (!fwrite(h,3,1,f)) return eXMLErrorCannotWriteFile;
+ }
+ }
+#endif
+ if (!fwrite(t,sizeof(XMLCHAR)*i,1,f)) return eXMLErrorCannotWriteFile;
+ if (fclose(f)!=0) return eXMLErrorCannotWriteFile;
+ free(t);
+ return eXMLErrorNone;
+}
+
+// Duplicate a given string.
+XMLSTR stringDup(XMLCSTR lpszData, int cbData)
+{
+ if (lpszData==NULL) return NULL;
+
+ XMLSTR lpszNew;
+ if (cbData==0) cbData=(int)_tcslen(lpszData);
+ lpszNew = (XMLSTR)malloc((cbData+1) * sizeof(XMLCHAR));
+ if (lpszNew)
+ {
+ memcpy(lpszNew, lpszData, (cbData) * sizeof(XMLCHAR));
+ lpszNew[cbData] = (XMLCHAR)NULL;
+ }
+ return lpszNew;
+}
+
+XMLNode XMLNode::emptyXMLNode;
+XMLClear XMLNode::emptyXMLClear={ NULL, NULL, NULL};
+XMLAttribute XMLNode::emptyXMLAttribute={ NULL, NULL};
+
+// Enumeration used to decipher what type a token is
+typedef enum XMLTokenTypeTag
+{
+ eTokenText = 0,
+ eTokenQuotedText,
+ eTokenTagStart, /* "<" */
+ eTokenTagEnd, /* "</" */
+ eTokenCloseTag, /* ">" */
+ eTokenEquals, /* "=" */
+ eTokenDeclaration, /* "<?" */
+ eTokenShortHandClose, /* "/>" */
+ eTokenClear,
+ eTokenError
+} XMLTokenType;
+
+// Main structure used for parsing XML
+typedef struct XML
+{
+ XMLCSTR lpXML;
+ XMLCSTR lpszText;
+ int nIndex,nIndexMissigEndTag;
+ enum XMLError error;
+ XMLCSTR lpEndTag;
+ int cbEndTag;
+ XMLCSTR lpNewElement;
+ int cbNewElement;
+ int nFirst;
+} XML;
+
+typedef struct
+{
+ ALLXMLClearTag *pClr;
+ XMLCSTR pStr;
+} NextToken;
+
+// Enumeration used when parsing attributes
+typedef enum Attrib
+{
+ eAttribName = 0,
+ eAttribEquals,
+ eAttribValue
+} Attrib;
+
+// Enumeration used when parsing elements to dictate whether we are currently
+// inside a tag
+typedef enum Status
+{
+ eInsideTag = 0,
+ eOutsideTag
+} Status;
+
+// private (used while rendering):
+XMLSTR toXMLString(XMLSTR dest,XMLCSTR source)
+{
+ XMLSTR dd=dest;
+ XMLCHAR ch;
+ XMLCharacterEntity *entity;
+ while ((ch=*source))
+ {
+ entity=XMLEntities;
+ do
+ {
+ if (ch==entity->c) {_tcscpy(dest,entity->s); dest+=entity->l; source++; goto out_of_loop1; }
+ entity++;
+ } while(entity->s);
+#ifdef _XMLUNICODE
+ *(dest++)=*(source++);
+#else
+ switch(XML_ByteTable[(unsigned char)ch])
+ {
+ case 4: *(dest++)=*(source++);
+ case 3: *(dest++)=*(source++);
+ case 2: *(dest++)=*(source++);
+ case 1: *(dest++)=*(source++);
+ }
+#endif
+out_of_loop1:
+ ;
+ }
+ *dest=0;
+ return dd;
+}
+
+// private (used while rendering):
+int lengthXMLString(XMLCSTR source)
+{
+ int r=0;
+ XMLCharacterEntity *entity;
+ XMLCHAR ch;
+ while ((ch=*source))
+ {
+ entity=XMLEntities;
+ do
+ {
+ if (ch==entity->c) { r+=entity->l; source++; goto out_of_loop1; }
+ entity++;
+ } while(entity->s);
+#ifdef _XMLUNICODE
+ r++; source++;
+#else
+ ch=XML_ByteTable[(unsigned char)ch]; r+=ch; source+=ch;
+#endif
+out_of_loop1:
+ ;
+ }
+ return r;
+}
+
+XMLSTR toXMLString(XMLCSTR source)
+{
+ XMLSTR dest=(XMLSTR)malloc((lengthXMLString(source)+1)*sizeof(XMLCHAR));
+ return toXMLString(dest,source);
+}
+
+XMLSTR toXMLStringFast(XMLSTR *dest,int *destSz, XMLCSTR source)
+{
+ int l=lengthXMLString(source)+1;
+ if (l>*destSz) { *destSz=l; *dest=(XMLSTR)realloc(*dest,l*sizeof(XMLCHAR)); }
+ return toXMLString(*dest,source);
+}
+
+// private:
+XMLSTR fromXMLString(XMLCSTR s, int lo, XML *pXML)
+{
+ // This function is the opposite of the function "toXMLString". It decodes the escape
+ // sequences &, ", ', <, > and replace them by the characters
+ // &,",',<,>. This function is used internally by the XML Parser. All the calls to
+ // the XML library will always gives you back "decoded" strings.
+ //
+ // in: string (s) and length (lo) of string
+ // out: new allocated string converted from xml
+ if (!s) return NULL;
+
+ int ll=0,j;
+ XMLSTR d;
+ XMLCSTR ss=s;
+ XMLCharacterEntity *entity;
+ while ((lo>0)&&(*s))
+ {
+ if (*s==_T('&'))
+ {
+ if ((lo>2)&&(s[1]==_T('#')))
+ {
+ s+=2; lo-=2;
+ if ((*s==_T('X'))||(*s==_T('x'))) { s++; lo--; }
+ while ((*s)&&(*s!=_T(';'))&&((lo--)>0)) s++;
+ if (*s!=_T(';'))
+ {
+ pXML->error=eXMLErrorUnknownCharacterEntity;
+ return NULL;
+ }
+ s++; lo--;
+ } else
+ {
+ entity=XMLEntities;
+ do
+ {
+ if ((lo>=entity->l)&&(_tcsnicmp(s,entity->s,entity->l)==0)) { s+=entity->l; lo-=entity->l; break; }
+ entity++;
+ } while(entity->s);
+ if (!entity->s)
+ {
+ pXML->error=eXMLErrorUnknownCharacterEntity;
+ return NULL;
+ }
+ }
+ } else
+ {
+#ifdef _XMLUNICODE
+ s++; lo--;
+#else
+ j=XML_ByteTable[(unsigned char)*s]; s+=j; lo-=j; ll+=j-1;
+#endif
+ }
+ ll++;
+ }
+
+ d=(XMLSTR)malloc((ll+1)*sizeof(XMLCHAR));
+ s=d;
+ while (ll-->0)
+ {
+ if (*ss==_T('&'))
+ {
+ if (ss[1]==_T('#'))
+ {
+ ss+=2; j=0;
+ if ((*ss==_T('X'))||(*ss==_T('x')))
+ {
+ ss++;
+ while (*ss!=_T(';'))
+ {
+ if ((*ss>=_T('0'))&&(*ss<=_T('9'))) j=(j<<4)+*ss-_T('0');
+ else if ((*ss>=_T('A'))&&(*ss<=_T('F'))) j=(j<<4)+*ss-_T('A')+10;
+ else if ((*ss>=_T('a'))&&(*ss<=_T('f'))) j=(j<<4)+*ss-_T('a')+10;
+ else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;}
+ ss++;
+ }
+ } else
+ {
+ while (*ss!=_T(';'))
+ {
+ if ((*ss>=_T('0'))&&(*ss<=_T('9'))) j=(j*10)+*ss-_T('0');
+ else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;}
+ ss++;
+ }
+ }
+ (*d++)=(XMLCHAR)j; ss++;
+ } else
+ {
+ entity=XMLEntities;
+ do
+ {
+ if (_tcsnicmp(ss,entity->s,entity->l)==0) { *(d++)=entity->c; ss+=entity->l; break; }
+ entity++;
+ } while(entity->s);
+ }
+ } else
+ {
+#ifdef _XMLUNICODE
+ *(d++)=*(ss++);
+#else
+ switch(XML_ByteTable[(unsigned char)*ss])
+ {
+ case 4: *(d++)=*(ss++); ll--;
+ case 3: *(d++)=*(ss++); ll--;
+ case 2: *(d++)=*(ss++); ll--;
+ case 1: *(d++)=*(ss++);
+ }
+#endif
+ }
+ }
+ *d=0;
+ return (XMLSTR)s;
+}
+
+#define XML_isSPACECHAR(ch) ((ch==_T('\n'))||(ch==_T(' '))||(ch== _T('\t'))||(ch==_T('\r')))
+
+// private:
+char myTagCompare(XMLCSTR cclose, XMLCSTR copen)
+// !!!! WARNING strange convention&:
+// return 0 if equals
+// return 1 if different
+{
+ if (!cclose) return 1;
+ int l=(int)_tcslen(cclose);
+ if (_tcsnicmp(cclose, copen, l)!=0) return 1;
+ const XMLCHAR c=copen[l];
+ if (XML_isSPACECHAR(c)||
+ (c==_T('/' ))||
+ (c==_T('<' ))||
+ (c==_T('>' ))||
+ (c==_T('=' ))) return 0;
+ return 1;
+}
+
+// Obtain the next character from the string.
+static inline XMLCHAR getNextChar(XML *pXML)
+{
+ XMLCHAR ch = pXML->lpXML[pXML->nIndex];
+#ifdef _XMLUNICODE
+ if (ch!=0) pXML->nIndex++;
+#else
+ pXML->nIndex+=XML_ByteTable[(unsigned char)ch];
+#endif
+ return ch;
+}
+
+// Find the next token in a string.
+// pcbToken contains the number of characters that have been read.
+static NextToken GetNextToken(XML *pXML, int *pcbToken, enum XMLTokenTypeTag *pType)
+{
+ NextToken result;
+ XMLCHAR ch;
+ XMLCHAR chTemp;
+ int indexStart,nFoundMatch,nIsText=FALSE;
+ result.pClr=NULL; // prevent warning
+
+ // Find next non-white space character
+ do { indexStart=pXML->nIndex; ch=getNextChar(pXML); } while XML_isSPACECHAR(ch);
+
+ if (ch)
+ {
+ // Cache the current string pointer
+ result.pStr = &pXML->lpXML[indexStart];
+
+ // First check whether the token is in the clear tag list (meaning it
+ // does not need formatting).
+ ALLXMLClearTag *ctag=XMLClearTags;
+ do
+ {
+ if (_tcsnicmp(ctag->lpszOpen, result.pStr, ctag->openTagLen)==0)
+ {
+ result.pClr=ctag;
+ pXML->nIndex+=ctag->openTagLen-1;
+ *pType=eTokenClear;
+ return result;
+ }
+ ctag++;
+ } while(ctag->lpszOpen);
+
+ // If we didn't find a clear tag then check for standard tokens
+ switch(ch)
+ {
+ // Check for quotes
+ case _T('\''):
+ case _T('\"'):
+ // Type of token
+ *pType = eTokenQuotedText;
+ chTemp = ch;
+
+ // Set the size
+ nFoundMatch = FALSE;
+
+ // Search through the string to find a matching quote
+ while((ch = getNextChar(pXML)))
+ {
+ if (ch==chTemp) { nFoundMatch = TRUE; break; }
+ if (ch==_T('<')) break;
+ }
+
+ // If we failed to find a matching quote
+ if (nFoundMatch == FALSE)
+ {
+ pXML->nIndex=indexStart+1;
+ nIsText=TRUE;
+ break;
+ }
+
+// 4.02.2002
+// if (FindNonWhiteSpace(pXML)) pXML->nIndex--;
+
+ break;
+
+ // Equals (used with attribute values)
+ case _T('='):
+ *pType = eTokenEquals;
+ break;
+
+ // Close tag
+ case _T('>'):
+ *pType = eTokenCloseTag;
+ break;
+
+ // Check for tag start and tag end
+ case _T('<'):
+
+ // Peek at the next character to see if we have an end tag '</',
+ // or an xml declaration '<?'
+ chTemp = pXML->lpXML[pXML->nIndex];
+
+ // If we have a tag end...
+ if (chTemp == _T('/'))
+ {
+ // Set the type and ensure we point at the next character
+ getNextChar(pXML);
+ *pType = eTokenTagEnd;
+ }
+
+ // If we have an XML declaration tag
+ else if (chTemp == _T('?'))
+ {
+
+ // Set the type and ensure we point at the next character
+ getNextChar(pXML);
+ *pType = eTokenDeclaration;
+ }
+
+ // Otherwise we must have a start tag
+ else
+ {
+ *pType = eTokenTagStart;
+ }
+ break;
+
+ // Check to see if we have a short hand type end tag ('/>').
+ case _T('/'):
+
+ // Peek at the next character to see if we have a short end tag '/>'
+ chTemp = pXML->lpXML[pXML->nIndex];
+
+ // If we have a short hand end tag...
+ if (chTemp == _T('>'))
+ {
+ // Set the type and ensure we point at the next character
+ getNextChar(pXML);
+ *pType = eTokenShortHandClose;
+ break;
+ }
+
+ // If we haven't found a short hand closing tag then drop into the
+ // text process
+
+ // Other characters
+ default:
+ nIsText = TRUE;
+ }
+
+ // If this is a TEXT node
+ if (nIsText)
+ {
+ // Indicate we are dealing with text
+ *pType = eTokenText;
+ while((ch = getNextChar(pXML)))
+ {
+ if XML_isSPACECHAR(ch)
+ {
+ indexStart++; break;
+
+ } else if (ch==_T('/'))
+ {
+ // If we find a slash then this maybe text or a short hand end tag
+ // Peek at the next character to see it we have short hand end tag
+ ch=pXML->lpXML[pXML->nIndex];
+ // If we found a short hand end tag then we need to exit the loop
+ if (ch==_T('>')) { pXML->nIndex--; break; }
+
+ } else if ((ch==_T('<'))||(ch==_T('>'))||(ch==_T('=')))
+ {
+ pXML->nIndex--; break;
+ }
+ }
+ }
+ *pcbToken = pXML->nIndex-indexStart;
+ } else
+ {
+ // If we failed to obtain a valid character
+ *pcbToken = 0;
+ *pType = eTokenError;
+ result.pStr=NULL;
+ }
+
+ return result;
+}
+
+XMLCSTR XMLNode::updateName_WOSD(XMLCSTR lpszName)
+{
+ if (d->lpszName&&(lpszName!=d->lpszName)) free((void*)d->lpszName);
+ d->lpszName=lpszName;
+ return lpszName;
+}
+
+// private:
+XMLNode::XMLNode(struct XMLNodeDataTag *p){ d=p; (p->ref_count)++; }
+XMLNode::XMLNode(XMLNodeData *pParent, XMLCSTR lpszName, char isDeclaration)
+{
+ d=(XMLNodeData*)malloc(sizeof(XMLNodeData));
+ d->ref_count=1;
+
+ d->lpszName=NULL;
+ d->nChild= 0;
+ d->nText = 0;
+ d->nClear = 0;
+ d->nAttribute = 0;
+
+ d->isDeclaration = isDeclaration;
+
+ d->pParent = pParent;
+ d->pChild= NULL;
+ d->pText= NULL;
+ d->pClear= NULL;
+ d->pAttribute= NULL;
+ d->pOrder= NULL;
+
+ updateName_WOSD(lpszName);
+}
+
+XMLNode XMLNode::createXMLTopNode_WOSD(XMLCSTR lpszName, char isDeclaration) { return XMLNode(NULL,lpszName,isDeclaration); }
+XMLNode XMLNode::createXMLTopNode(XMLCSTR lpszName, char isDeclaration) { return XMLNode(NULL,stringDup(lpszName),isDeclaration); }
+
+#define MEMORYINCREASE 50
+
+static inline void *myRealloc(void *p, int newsize, int memInc, int sizeofElem)
+{
+ if (p==NULL) { if (memInc) return malloc(memInc*sizeofElem); return malloc(sizeofElem); }
+ if ((memInc==0)||((newsize%memInc)==0)) p=realloc(p,(newsize+memInc)*sizeofElem);
+// if (!p)
+// {
+// printf("XMLParser Error: Not enough memory! Aborting...\n"); exit(220);
+// }
+ return p;
+}
+
+// private:
+int XMLNode::findPosition(XMLNodeData *d, int index, XMLElementType xtype)
+{
+ if (index<0) return -1;
+ int i=0,j=(int)((index<<2)+xtype),*o=d->pOrder; while (o[i]!=j) i++; return i;
+}
+
+// private:
+// update "order" information when deleting a content of a XMLNode
+int XMLNode::removeOrderElement(XMLNodeData *d, XMLElementType t, int index)
+{
+ int n=d->nChild+d->nText+d->nClear, *o=d->pOrder,i=findPosition(d,index,t);
+ memmove(o+i, o+i+1, (n-i)*sizeof(int));
+ for (;i<n;i++)
+ if ((o[i]&3)==(int)t) o[i]-=4;
+ // We should normally do:
+ // d->pOrder=(int)realloc(d->pOrder,n*sizeof(int));
+ // but we skip reallocation because it's too time consuming.
+ // Anyway, at the end, it will be free'd completely at once.
+ return i;
+}
+
+void *XMLNode::addToOrder(int memoryIncrease,int *_pos, int nc, void *p, int size, XMLElementType xtype)
+{
+ // in: *_pos is the position inside d->pOrder ("-1" means "EndOf")
+ // out: *_pos is the index inside p
+ p=myRealloc(p,(nc+1),memoryIncrease,size);
+ int n=d->nChild+d->nText+d->nClear;
+ d->pOrder=(int*)myRealloc(d->pOrder,n+1,memoryIncrease*3,sizeof(int));
+ int pos=*_pos,*o=d->pOrder;
+
+ if ((pos<0)||(pos>=n)) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; }
+
+ int i=pos;
+ memmove(o+i+1, o+i, (n-i)*sizeof(int));
+
+ while ((pos<n)&&((o[pos]&3)!=(int)xtype)) pos++;
+ if (pos==n) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; }
+
+ o[i]=o[pos];
+ for (i=pos+1;i<=n;i++) if ((o[i]&3)==(int)xtype) o[i]+=4;
+
+ *_pos=pos=o[pos]>>2;
+ memmove(((char*)p)+(pos+1)*size,((char*)p)+pos*size,(nc-pos)*size);
+
+ return p;
+}
+
+// Add a child node to the given element.
+XMLNode XMLNode::addChild_priv(int memoryIncrease, XMLCSTR lpszName, char isDeclaration, int pos)
+{
+ if (!lpszName) return emptyXMLNode;
+ d->pChild=(XMLNode*)addToOrder(memoryIncrease,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild);
+ d->pChild[pos].d=NULL;
+ d->pChild[pos]=XMLNode(d,lpszName,isDeclaration);
+ d->nChild++;
+ return d->pChild[pos];
+}
+
+// Add an attribute to an element.
+XMLAttribute *XMLNode::addAttribute_priv(int memoryIncrease,XMLCSTR lpszName, XMLCSTR lpszValuev)
+{
+ if (!lpszName) return &emptyXMLAttribute;
+ int nc=d->nAttribute;
+ d->pAttribute=(XMLAttribute*)myRealloc(d->pAttribute,(nc+1),memoryIncrease,sizeof(XMLAttribute));
+ XMLAttribute *pAttr=d->pAttribute+nc;
+ pAttr->lpszName = lpszName;
+ pAttr->lpszValue = lpszValuev;
+ d->nAttribute++;
+ return pAttr;
+}
+
+// Add text to the element.
+XMLCSTR XMLNode::addText_priv(int memoryIncrease, XMLCSTR lpszValue, int pos)
+{
+ if (!lpszValue) return NULL;
+ d->pText=(XMLCSTR*)addToOrder(memoryIncrease,&pos,d->nText,d->pText,sizeof(XMLSTR),eNodeText);
+ d->pText[pos]=lpszValue;
+ d->nText++;
+ return lpszValue;
+}
+
+// Add clear (unformatted) text to the element.
+XMLClear *XMLNode::addClear_priv(int memoryIncrease, XMLCSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos)
+{
+ if (!lpszValue) return &emptyXMLClear;
+ d->pClear=(XMLClear *)addToOrder(memoryIncrease,&pos,d->nClear,d->pClear,sizeof(XMLClear),eNodeClear);
+ XMLClear *pNewClear=d->pClear+pos;
+ pNewClear->lpszValue = lpszValue;
+ if (!lpszOpen) lpszOpen=getClearTagTable()->lpszOpen;
+ if (!lpszClose) lpszOpen=getClearTagTable()->lpszClose;
+ pNewClear->lpszOpenTag = lpszOpen;
+ pNewClear->lpszCloseTag = lpszClose;
+ d->nClear++;
+ return pNewClear;
+}
+
+// private:
+// Parse a clear (unformatted) type node.
+char XMLNode::parseClearTag(void *px, ALLXMLClearTag *pClear)
+{
+ XML *pXML=(XML *)px;
+ int cbTemp=0;
+ XMLCSTR lpszTemp=NULL;
+ XMLCSTR lpXML=&pXML->lpXML[pXML->nIndex];
+ static XMLCSTR docTypeEnd=_T("]>");
+
+ // Find the closing tag
+ // Seems the <!DOCTYPE need a better treatment so lets handle it
+ if (pClear->lpszOpen==XMLClearTags[1].lpszOpen)
+ {
+ XMLCSTR pCh=lpXML;
+ while (*pCh)
+ {
+ if (*pCh==_T('<')) { pClear->lpszClose=docTypeEnd; lpszTemp=_tcsstr(lpXML,docTypeEnd); break; }
+ else if (*pCh==_T('>')) { lpszTemp=pCh; break; }
+#ifdef _XMLUNICODE
+ pCh++;
+#else
+ pCh+=XML_ByteTable[(unsigned char)(*pCh)];
+#endif
+ }
+ } else lpszTemp=_tcsstr(lpXML, pClear->lpszClose);
+
+ if (lpszTemp)
+ {
+ // Cache the size and increment the index
+ cbTemp = (int)(lpszTemp - lpXML);
+
+ pXML->nIndex += cbTemp+(int)_tcslen(pClear->lpszClose);
+
+ // Add the clear node to the current element
+ addClear_priv(MEMORYINCREASE,stringDup(lpXML,cbTemp), pClear->lpszOpen, pClear->lpszClose,-1);
+ return 0;
+ }
+
+ // If we failed to find the end tag
+ pXML->error = eXMLErrorUnmatchedEndClearTag;
+ return 1;
+}
+
+void XMLNode::exactMemory(XMLNodeData *d)
+{
+ if (d->pOrder) d->pOrder=(int*)realloc(d->pOrder,(d->nChild+d->nText+d->nClear)*sizeof(int));
+ if (d->pChild) d->pChild=(XMLNode*)realloc(d->pChild,d->nChild*sizeof(XMLNode));
+ if (d->pAttribute) d->pAttribute=(XMLAttribute*)realloc(d->pAttribute,d->nAttribute*sizeof(XMLAttribute));
+ if (d->pText) d->pText=(XMLCSTR*)realloc(d->pText,d->nText*sizeof(XMLSTR));
+ if (d->pClear) d->pClear=(XMLClear *)realloc(d->pClear,d->nClear*sizeof(XMLClear));
+}
+
+char XMLNode::maybeAddTxT(void *pa, XMLCSTR tokenPStr)
+{
+ XML *pXML=(XML *)pa;
+ XMLCSTR lpszText=pXML->lpszText;
+ if (!lpszText) return 0;
+ if (dropWhiteSpace) while (XML_isSPACECHAR(*lpszText)&&(lpszText!=tokenPStr)) lpszText++;
+ int cbText = (int)(tokenPStr - lpszText);
+ if (!cbText) { pXML->lpszText=NULL; return 0; }
+ if (dropWhiteSpace) { cbText--; while ((cbText)&&XML_isSPACECHAR(lpszText[cbText])) cbText--; cbText++; }
+ if (!cbText) { pXML->lpszText=NULL; return 0; }
+ lpszText=fromXMLString(lpszText,cbText,pXML);
+ if (!lpszText) return 1;
+ addText_priv(MEMORYINCREASE,lpszText,-1);
+ pXML->lpszText=NULL;
+ return 0;
+}
+// private:
+// Recursively parse an XML element.
+int XMLNode::ParseXMLElement(void *pa)
+{
+ XML *pXML=(XML *)pa;
+ int cbToken;
+ enum XMLTokenTypeTag type;
+ NextToken token;
+ XMLCSTR lpszTemp=NULL;
+ int cbTemp=0;
+ char nDeclaration;
+ XMLNode pNew;
+ enum Status status; // inside or outside a tag
+ enum Attrib attrib = eAttribName;
+
+ assert(pXML);
+
+ // If this is the first call to the function
+ if (pXML->nFirst)
+ {
+ // Assume we are outside of a tag definition
+ pXML->nFirst = FALSE;
+ status = eOutsideTag;
+ } else
+ {
+ // If this is not the first call then we should only be called when inside a tag.
+ status = eInsideTag;
+ }
+
+ // Iterate through the tokens in the document
+ for(;;)
+ {
+ // Obtain the next token
+ token = GetNextToken(pXML, &cbToken, &type);
+
+ if (type != eTokenError)
+ {
+ // Check the current status
+ switch(status)
+ {
+
+ // If we are outside of a tag definition
+ case eOutsideTag:
+
+ // Check what type of token we obtained
+ switch(type)
+ {
+ // If we have found text or quoted text
+ case eTokenText:
+ case eTokenCloseTag: /* '>' */
+ case eTokenShortHandClose: /* '/>' */
+ case eTokenQuotedText:
+ case eTokenEquals:
+ break;
+
+ // If we found a start tag '<' and declarations '<?'
+ case eTokenTagStart:
+ case eTokenDeclaration:
+
+ // Cache whether this new element is a declaration or not
+ nDeclaration = (type == eTokenDeclaration);
+
+ // If we have node text then add this to the element
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
+
+ // Find the name of the tag
+ token = GetNextToken(pXML, &cbToken, &type);
+
+ // Return an error if we couldn't obtain the next token or
+ // it wasnt text
+ if (type != eTokenText)
+ {
+ pXML->error = eXMLErrorMissingTagName;
+ return FALSE;
+ }
+
+ // If we found a new element which is the same as this
+ // element then we need to pass this back to the caller..
+
+#ifdef APPROXIMATE_PARSING
+ if (d->lpszName &&
+ myTagCompare(d->lpszName, token.pStr) == 0)
+ {
+ // Indicate to the caller that it needs to create a
+ // new element.
+ pXML->lpNewElement = token.pStr;
+ pXML->cbNewElement = cbToken;
+ return TRUE;
+ } else
+#endif
+ {
+ // If the name of the new element differs from the name of
+ // the current element we need to add the new element to
+ // the current one and recurse
+ pNew = addChild_priv(MEMORYINCREASE,stringDup(token.pStr,cbToken), nDeclaration,-1);
+
+ while (!pNew.isEmpty())
+ {
+ // Callself to process the new node. If we return
+ // FALSE this means we dont have any more
+ // processing to do...
+
+ if (!pNew.ParseXMLElement(pXML)) return FALSE;
+ else
+ {
+ // If the call to recurse this function
+ // evented in a end tag specified in XML then
+ // we need to unwind the calls to this
+ // function until we find the appropriate node
+ // (the element name and end tag name must
+ // match)
+ if (pXML->cbEndTag)
+ {
+ // If we are back at the root node then we
+ // have an unmatched end tag
+ if (!d->lpszName)
+ {
+ pXML->error=eXMLErrorUnmatchedEndTag;
+ return FALSE;
+ }
+
+ // If the end tag matches the name of this
+ // element then we only need to unwind
+ // once more...
+
+ if (myTagCompare(d->lpszName, pXML->lpEndTag)==0)
+ {
+ pXML->cbEndTag = 0;
+ }
+
+ return TRUE;
+ } else
+ if (pXML->cbNewElement)
+ {
+ // If the call indicated a new element is to
+ // be created on THIS element.
+
+ // If the name of this element matches the
+ // name of the element we need to create
+ // then we need to return to the caller
+ // and let it process the element.
+
+ if (myTagCompare(d->lpszName, pXML->lpNewElement)==0)
+ {
+ return TRUE;
+ }
+
+ // Add the new element and recurse
+ pNew = addChild_priv(MEMORYINCREASE,stringDup(pXML->lpNewElement,pXML->cbNewElement),0,-1);
+ pXML->cbNewElement = 0;
+ }
+ else
+ {
+ // If we didn't have a new element to create
+ pNew = emptyXMLNode;
+
+ }
+ }
+ }
+ }
+ break;
+
+ // If we found an end tag
+ case eTokenTagEnd:
+
+ // If we have node text then add this to the element
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
+
+ // Find the name of the end tag
+ token = GetNextToken(pXML, &cbTemp, &type);
+
+ // The end tag should be text
+ if (type != eTokenText)
+ {
+ pXML->error = eXMLErrorMissingEndTagName;
+ return FALSE;
+ }
+ lpszTemp = token.pStr;
+
+ // After the end tag we should find a closing tag
+ token = GetNextToken(pXML, &cbToken, &type);
+ if (type != eTokenCloseTag)
+ {
+ pXML->error = eXMLErrorMissingEndTagName;
+ return FALSE;
+ }
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+
+ // We need to return to the previous caller. If the name
+ // of the tag cannot be found we need to keep returning to
+ // caller until we find a match
+ if (myTagCompare(d->lpszName, lpszTemp) != 0)
+#ifdef STRICT_PARSING
+ {
+ pXML->error=eXMLErrorUnmatchedEndTag;
+ pXML->nIndexMissigEndTag=pXML->nIndex;
+ return FALSE;
+ }
+#else
+ {
+ pXML->error=eXMLErrorMissingEndTag;
+ pXML->nIndexMissigEndTag=pXML->nIndex;
+ pXML->lpEndTag = lpszTemp;
+ pXML->cbEndTag = cbTemp;
+ }
+#endif
+
+ // Return to the caller
+ exactMemory(d);
+ return TRUE;
+
+ // If we found a clear (unformatted) token
+ case eTokenClear:
+ // If we have node text then add this to the element
+ if (maybeAddTxT(pXML,token.pStr)) return FALSE;
+ if (parseClearTag(pXML, token.pClr)) return FALSE;
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ // If we are inside a tag definition we need to search for attributes
+ case eInsideTag:
+
+ // Check what part of the attribute (name, equals, value) we
+ // are looking for.
+ switch(attrib)
+ {
+ // If we are looking for a new attribute
+ case eAttribName:
+
+ // Check what the current token type is
+ switch(type)
+ {
+ // If the current type is text...
+ // Eg. 'attribute'
+ case eTokenText:
+ // Cache the token then indicate that we are next to
+ // look for the equals
+ lpszTemp = token.pStr;
+ cbTemp = cbToken;
+ attrib = eAttribEquals;
+ break;
+
+ // If we found a closing tag...
+ // Eg. '>'
+ case eTokenCloseTag:
+ // We are now outside the tag
+ status = eOutsideTag;
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+ break;
+
+ // If we found a short hand '/>' closing tag then we can
+ // return to the caller
+ case eTokenShortHandClose:
+ exactMemory(d);
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+ return TRUE;
+
+ // Errors...
+ case eTokenQuotedText: /* '"SomeText"' */
+ case eTokenTagStart: /* '<' */
+ case eTokenTagEnd: /* '</' */
+ case eTokenEquals: /* '=' */
+ case eTokenDeclaration: /* '<?' */
+ case eTokenClear:
+ pXML->error = eXMLErrorUnexpectedToken;
+ return FALSE;
+ default: break;
+ }
+ break;
+
+ // If we are looking for an equals
+ case eAttribEquals:
+ // Check what the current token type is
+ switch(type)
+ {
+ // If the current type is text...
+ // Eg. 'Attribute AnotherAttribute'
+ case eTokenText:
+ // Add the unvalued attribute to the list
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL);
+ // Cache the token then indicate. We are next to
+ // look for the equals attribute
+ lpszTemp = token.pStr;
+ cbTemp = cbToken;
+ break;
+
+ // If we found a closing tag 'Attribute >' or a short hand
+ // closing tag 'Attribute />'
+ case eTokenShortHandClose:
+ case eTokenCloseTag:
+ // If we are a declaration element '<?' then we need
+ // to remove extra closing '?' if it exists
+ pXML->lpszText=pXML->lpXML+pXML->nIndex;
+
+ if (d->isDeclaration &&
+ (lpszTemp[cbTemp-1]) == _T('?'))
+ {
+ cbTemp--;
+ }
+
+ if (cbTemp)
+ {
+ // Add the unvalued attribute to the list
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL);
+ }
+
+ // If this is the end of the tag then return to the caller
+ if (type == eTokenShortHandClose)
+ {
+ exactMemory(d);
+ return TRUE;
+ }
+
+ // We are now outside the tag
+ status = eOutsideTag;
+ break;
+
+ // If we found the equals token...
+ // Eg. 'Attribute ='
+ case eTokenEquals:
+ // Indicate that we next need to search for the value
+ // for the attribute
+ attrib = eAttribValue;
+ break;
+
+ // Errors...
+ case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/
+ case eTokenTagStart: /* 'Attribute <' */
+ case eTokenTagEnd: /* 'Attribute </' */
+ case eTokenDeclaration: /* 'Attribute <?' */
+ case eTokenClear:
+ pXML->error = eXMLErrorUnexpectedToken;
+ return FALSE;
+ default: break;
+ }
+ break;
+
+ // If we are looking for an attribute value
+ case eAttribValue:
+ // Check what the current token type is
+ switch(type)
+ {
+ // If the current type is text or quoted text...
+ // Eg. 'Attribute = "Value"' or 'Attribute = Value' or
+ // 'Attribute = 'Value''.
+ case eTokenText:
+ case eTokenQuotedText:
+ // If we are a declaration element '<?' then we need
+ // to remove extra closing '?' if it exists
+ if (d->isDeclaration &&
+ (token.pStr[cbToken-1]) == _T('?'))
+ {
+ cbToken--;
+ }
+
+ if (cbTemp)
+ {
+ // Add the valued attribute to the list
+ if (type==eTokenQuotedText) { token.pStr++; cbToken-=2; }
+ XMLCSTR attrVal=token.pStr;
+ if (attrVal)
+ {
+ attrVal=fromXMLString(attrVal,cbToken,pXML);
+ if (!attrVal) return FALSE;
+ }
+ addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp),attrVal);
+ }
+
+ // Indicate we are searching for a new attribute
+ attrib = eAttribName;
+ break;
+
+ // Errors...
+ case eTokenTagStart: /* 'Attr = <' */
+ case eTokenTagEnd: /* 'Attr = </' */
+ case eTokenCloseTag: /* 'Attr = >' */
+ case eTokenShortHandClose: /* "Attr = />" */
+ case eTokenEquals: /* 'Attr = =' */
+ case eTokenDeclaration: /* 'Attr = <?' */
+ case eTokenClear:
+ pXML->error = eXMLErrorUnexpectedToken;
+ return FALSE;
+ break;
+ default: break;
+ }
+ }
+ }
+ }
+ // If we failed to obtain the next token
+ else
+ {
+ if ((!d->isDeclaration)&&(d->pParent))
+ {
+#ifdef STRICT_PARSING
+ pXML->error=eXMLErrorUnmatchedEndTag;
+#else
+ pXML->error=eXMLErrorMissingEndTag;
+#endif
+ pXML->nIndexMissigEndTag=pXML->nIndex;
+ }
+ return FALSE;
+ }
+ }
+}
+
+// Count the number of lines and columns in an XML string.
+static void CountLinesAndColumns(XMLCSTR lpXML, int nUpto, XMLResults *pResults)
+{
+ XMLCHAR ch;
+ assert(lpXML);
+ assert(pResults);
+
+ struct XML xml={ lpXML,lpXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE };
+
+ pResults->nLine = 1;
+ pResults->nColumn = 1;
+ while (xml.nIndex<nUpto)
+ {
+ ch = getNextChar(&xml);
+ if (ch != _T('\n')) pResults->nColumn++;
+ else
+ {
+ pResults->nLine++;
+ pResults->nColumn=1;
+ }
+ }
+}
+
+// Parse XML and return the root element.
+XMLNode XMLNode::parseString(XMLCSTR lpszXML, XMLCSTR tag, XMLResults *pResults)
+{
+ if (!lpszXML)
+ {
+ if (pResults)
+ {
+ pResults->error=eXMLErrorNoElements;
+ pResults->nLine=0;
+ pResults->nColumn=0;
+ }
+ return emptyXMLNode;
+ }
+
+ XMLNode xnode(NULL,NULL,FALSE);
+ struct XML xml={ lpszXML, lpszXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE };
+
+ // Create header element
+ xnode.ParseXMLElement(&xml);
+ enum XMLError error = xml.error;
+ if ((xnode.nChildNode()==1)&&(xnode.nElement()==1)) xnode=xnode.getChildNode(); // skip the empty node
+
+ // If no error occurred
+ if ((error==eXMLErrorNone)||(error==eXMLErrorMissingEndTag))
+ {
+ XMLCSTR name=xnode.getName();
+ if (tag&&_tcslen(tag)&&((!name)||(_tcsicmp(xnode.getName(),tag))))
+ {
+ XMLNode nodeTmp;
+ int i=0;
+ while (i<xnode.nChildNode())
+ {
+ nodeTmp=xnode.getChildNode(i);
+ if (_tcsicmp(nodeTmp.getName(),tag)==0) break;
+ if (nodeTmp.isDeclaration()) { xnode=nodeTmp; i=0; } else i++;
+ }
+ if (i>=xnode.nChildNode())
+ {
+ if (pResults)
+ {
+ pResults->error=eXMLErrorFirstTagNotFound;
+ pResults->nLine=0;
+ pResults->nColumn=0;
+ }
+ return emptyXMLNode;
+ }
+ xnode=nodeTmp;
+ }
+ } else
+ {
+ // Cleanup: this will destroy all the nodes
+ xnode = emptyXMLNode;
+ }
+
+
+ // If we have been given somewhere to place results
+ if (pResults)
+ {
+ pResults->error = error;
+
+ // If we have an error
+ if (error!=eXMLErrorNone)
+ {
+ if (error==eXMLErrorMissingEndTag) xml.nIndex=xml.nIndexMissigEndTag;
+ // Find which line and column it starts on.
+ CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults);
+ }
+ }
+ return xnode;
+}
+
+XMLNode XMLNode::parseFile(XMLCSTR filename, XMLCSTR tag, XMLResults *pResults)
+{
+ if (pResults) { pResults->nLine=0; pResults->nColumn=0; }
+ FILE *f=_tfopen(filename,_T("rb"));
+ if (f==NULL) { if (pResults) pResults->error=eXMLErrorFileNotFound; return emptyXMLNode; }
+ fseek(f,0,SEEK_END);
+ int l=ftell(f),headerSz=0;
+ if (!l) { if (pResults) pResults->error=eXMLErrorEmpty; return emptyXMLNode; }
+ fseek(f,0,SEEK_SET);
+ unsigned char *buf=(unsigned char*)malloc(l+1);
+ fread(buf,l,1,f);
+ fclose(f);
+ buf[l]=0;
+#ifdef _XMLUNICODE
+ if (guessUnicodeChars)
+ {
+ if (!myIsTextUnicode(buf,l))
+ {
+ if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3;
+ XMLSTR b2=myMultiByteToWideChar((const char*)(buf+headerSz),l-headerSz);
+ free(buf); buf=(unsigned char*)b2; headerSz=0;
+ } else
+ {
+ if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2;
+ if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2;
+ }
+ }
+#else
+ if (guessUnicodeChars)
+ {
+ if (myIsTextUnicode(buf,l))
+ {
+ l/=sizeof(wchar_t);
+ if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2;
+ if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2;
+ char *b2=myWideCharToMultiByte((const wchar_t*)(buf+headerSz),l-headerSz);
+ free(buf); buf=(unsigned char*)b2; headerSz=0;
+ } else
+ {
+ if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3;
+ }
+ }
+#endif
+
+ if (!buf) { if (pResults) pResults->error=eXMLErrorCharConversionError; return emptyXMLNode; }
+ XMLNode x=parseString((XMLSTR)(buf+headerSz),tag,pResults);
+ free(buf);
+ return x;
+}
+
+static inline void charmemset(XMLSTR dest,XMLCHAR c,int l) { while (l--) *(dest++)=c; }
+// private:
+// Creates an user friendly XML string from a given element with
+// appropriate white space and carriage returns.
+//
+// This recurses through all subnodes then adds contents of the nodes to the
+// string.
+int XMLNode::CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat)
+{
+ int nResult = 0;
+ int cb;
+ int cbElement;
+ int nChildFormat=-1;
+ int nElementI=pEntry->nChild+pEntry->nText+pEntry->nClear;
+ int i,j;
+
+ assert(pEntry);
+
+#define LENSTR(lpsz) (lpsz ? _tcslen(lpsz) : 0)
+
+ // If the element has no name then assume this is the head node.
+ cbElement = (int)LENSTR(pEntry->lpszName);
+
+ if (cbElement)
+ {
+ // "<elementname "
+ cb = nFormat == -1 ? 0 : nFormat;
+
+ if (lpszMarker)
+ {
+ if (cb) charmemset(lpszMarker, INDENTCHAR, sizeof(XMLCHAR)*cb);
+ nResult = cb;
+ lpszMarker[nResult++]=_T('<');
+ if (pEntry->isDeclaration) lpszMarker[nResult++]=_T('?');
+ _tcscpy(&lpszMarker[nResult], pEntry->lpszName);
+ nResult+=cbElement;
+ lpszMarker[nResult++]=_T(' ');
+
+ } else
+ {
+ nResult+=cbElement+2+cb;
+ if (pEntry->isDeclaration) nResult++;
+ }
+
+ // Enumerate attributes and add them to the string
+ XMLAttribute *pAttr=pEntry->pAttribute;
+ for (i=0; i<pEntry->nAttribute; i++)
+ {
+ // "Attrib
+ cb = (int)LENSTR(pAttr->lpszName);
+ if (cb)
+ {
+ if (lpszMarker) _tcscpy(&lpszMarker[nResult], pAttr->lpszName);
+ nResult += cb;
+ // "Attrib=Value "
+ if (pAttr->lpszValue)
+ {
+ cb=(int)lengthXMLString(pAttr->lpszValue);
+ if (lpszMarker)
+ {
+ lpszMarker[nResult]=_T('=');
+ lpszMarker[nResult+1]=_T('"');
+ if (cb) toXMLString(&lpszMarker[nResult+2],pAttr->lpszValue);
+ lpszMarker[nResult+cb+2]=_T('"');
+ }
+ nResult+=cb+3;
+ }
+ if (lpszMarker) lpszMarker[nResult] = _T(' ');
+ nResult++;
+ }
+ pAttr++;
+ }
+
+ if (pEntry->isDeclaration)
+ {
+ if (lpszMarker)
+ {
+ lpszMarker[nResult-1]=_T('?');
+ lpszMarker[nResult]=_T('>');
+ }
+ nResult++;
+ if (nFormat!=-1)
+ {
+ if (lpszMarker) lpszMarker[nResult]=_T('\n');
+ nResult++;
+ }
+ } else
+ // If there are child nodes we need to terminate the start tag
+ if (nElementI)
+ {
+ if (lpszMarker) lpszMarker[nResult-1]=_T('>');
+ if (nFormat!=-1)
+ {
+ if (lpszMarker) lpszMarker[nResult]=_T('\n');
+ nResult++;
+ }
+ } else nResult--;
+ }
+
+ // Calculate the child format for when we recurse. This is used to
+ // determine the number of spaces used for prefixes.
+ if (nFormat!=-1)
+ {
+ if (cbElement&&(!pEntry->isDeclaration)) nChildFormat=nFormat+1;
+ else nChildFormat=nFormat;
+ }
+
+ // Enumerate through remaining children
+ for (i=0; i<nElementI; i++)
+ {
+ j=pEntry->pOrder[i];
+ switch((XMLElementType)(j&3))
+ {
+ // Text nodes
+ case eNodeText:
+ {
+ // "Text"
+ XMLCSTR pChild=pEntry->pText[j>>2];
+ cb = (int)lengthXMLString(pChild);
+ if (cb)
+ {
+ if (nFormat!=-1)
+ {
+ if (lpszMarker)
+ {
+ charmemset(&lpszMarker[nResult],INDENTCHAR,sizeof(XMLCHAR)*(nFormat + 1));
+ toXMLString(&lpszMarker[nResult+nFormat+1],pChild);
+ lpszMarker[nResult+nFormat+1+cb]=_T('\n');
+ }
+ nResult+=cb+nFormat+2;
+ } else
+ {
+ if (lpszMarker) toXMLString(&lpszMarker[nResult], pChild);
+ nResult += cb;
+ }
+ }
+ break;
+ }
+
+ // Clear type nodes
+ case eNodeClear:
+ {
+ XMLClear *pChild=pEntry->pClear+(j>>2);
+ // "OpenTag"
+ cb = (int)LENSTR(pChild->lpszOpenTag);
+ if (cb)
+ {
+ if (nFormat!=-1)
+ {
+ if (lpszMarker)
+ {
+ charmemset(&lpszMarker[nResult], INDENTCHAR, sizeof(XMLCHAR)*(nFormat + 1));
+ _tcscpy(&lpszMarker[nResult+nFormat+1], pChild->lpszOpenTag);
+ }
+ nResult+=cb+nFormat+1;
+ }
+ else
+ {
+ if (lpszMarker)_tcscpy(&lpszMarker[nResult], pChild->lpszOpenTag);
+ nResult += cb;
+ }
+ }
+
+ // "OpenTag Value"
+ cb = (int)LENSTR(pChild->lpszValue);
+ if (cb)
+ {
+ if (lpszMarker) _tcscpy(&lpszMarker[nResult], pChild->lpszValue);
+ nResult += cb;
+ }
+
+ // "OpenTag Value CloseTag"
+ cb = (int)LENSTR(pChild->lpszCloseTag);
+ if (cb)
+ {
+ if (lpszMarker) _tcscpy(&lpszMarker[nResult], pChild->lpszCloseTag);
+ nResult += cb;
+ }
+
+ if (nFormat!=-1)
+ {
+ if (lpszMarker) lpszMarker[nResult] = _T('\n');
+ nResult++;
+ }
+ break;
+ }
+
+ // Element nodes
+ case eNodeChild:
+ {
+ // Recursively add child nodes
+ nResult += CreateXMLStringR(pEntry->pChild[j>>2].d, lpszMarker ? lpszMarker + nResult : 0, nChildFormat);
+ break;
+ }
+ default: break;
+ }
+ }
+
+ if ((cbElement)&&(!pEntry->isDeclaration))
+ {
+ // If we have child entries we need to use long XML notation for
+ // closing the element - "<elementname>blah blah blah</elementname>"
+ if (nElementI)
+ {
+ // "</elementname>\0"
+ if (lpszMarker)
+ {
+ if (nFormat != -1)
+ {
+ if (nFormat)
+ {
+ charmemset(&lpszMarker[nResult], INDENTCHAR,sizeof(XMLCHAR)*nFormat);
+ nResult+=nFormat;
+ }
+ }
+
+ _tcscpy(&lpszMarker[nResult], _T("</"));
+ nResult += 2;
+ _tcscpy(&lpszMarker[nResult], pEntry->lpszName);
+ nResult += cbElement;
+
+ if (nFormat == -1)
+ {
+ _tcscpy(&lpszMarker[nResult], _T(">"));
+ nResult++;
+ } else
+ {
+ _tcscpy(&lpszMarker[nResult], _T(">\n"));
+ nResult+=2;
+ }
+ } else
+ {
+ if (nFormat != -1) nResult+=cbElement+4+nFormat;
+ else nResult+=cbElement+3;
+ }
+ } else
+ {
+ // If there are no children we can use shorthand XML notation -
+ // "<elementname/>"
+ // "/>\0"
+ if (lpszMarker)
+ {
+ if (nFormat == -1)
+ {
+ _tcscpy(&lpszMarker[nResult], _T("/>"));
+ nResult += 2;
+ }
+ else
+ {
+ _tcscpy(&lpszMarker[nResult], _T("/>\n"));
+ nResult += 3;
+ }
+ }
+ else
+ {
+ nResult += nFormat == -1 ? 2 : 3;
+ }
+ }
+ }
+
+ return nResult;
+}
+
+#undef LENSTR
+
+// Create an XML string
+// @param int nFormat - 0 if no formatting is required
+// otherwise nonzero for formatted text
+// with carriage returns and indentation.
+// @param int *pnSize - [out] pointer to the size of the
+// returned string not including the
+// NULL terminator.
+// @return XMLSTR - Allocated XML string, you must free
+// this with free().
+XMLSTR XMLNode::createXMLString(int nFormat, int *pnSize) const
+{
+ if (!d) { if (pnSize) *pnSize=0; return NULL; }
+
+ XMLSTR lpszResult = NULL;
+ int cbStr;
+
+ // Recursively Calculate the size of the XML string
+ if (!dropWhiteSpace) nFormat=0;
+ nFormat = nFormat ? 0 : -1;
+ cbStr = CreateXMLStringR(d, 0, nFormat);
+ assert(cbStr);
+ // Alllocate memory for the XML string + the NULL terminator and
+ // create the recursively XML string.
+ lpszResult=(XMLSTR)malloc((cbStr+1)*sizeof(XMLCHAR));
+ CreateXMLStringR(d, lpszResult, nFormat);
+ if (pnSize) *pnSize = cbStr;
+ return lpszResult;
+}
+
+XMLNode::~XMLNode() { deleteNodeContent(); }
+
+int XMLNode::detachFromParent(XMLNodeData *d)
+{
+ XMLNode *pa=d->pParent->pChild;
+ int i=0;
+ while (((void*)(pa[i].d))!=((void*)d)) i++;
+ d->pParent->nChild--;
+ if (d->pParent->nChild) memmove(pa+i,pa+i+1,(d->pParent->nChild-i)*sizeof(XMLNode));
+ else { free(pa); d->pParent->pChild=NULL; }
+ return removeOrderElement(d->pParent,eNodeChild,i);
+}
+
+void XMLNode::deleteNodeContent(char force)
+{
+ if (!d) return;
+ (d->ref_count) --;
+ if ((d->ref_count==0)||force)
+ {
+ int i;
+ if (d->pParent) detachFromParent(d);
+ for(i=0; i<d->nChild; i++) { d->pChild[i].d->pParent=NULL; d->pChild[i].deleteNodeContent(force); }
+ free(d->pChild);
+ for(i=0; i<d->nText; i++) free((void*)d->pText[i]);
+ free(d->pText);
+ for(i=0; i<d->nClear; i++) free((void*)d->pClear[i].lpszValue);
+ free(d->pClear);
+ for(i=0; i<d->nAttribute; i++)
+ {
+ free((void*)d->pAttribute[i].lpszName);
+ if (d->pAttribute[i].lpszValue) free((void*)d->pAttribute[i].lpszValue);
+ }
+ free(d->pAttribute);
+ free(d->pOrder);
+ free((void*)d->lpszName);
+ free(d);
+ d=NULL;
+ }
+}
+
+XMLNode XMLNode::addChild(XMLNode childNode, int pos)
+{
+ XMLNodeData *dc=childNode.d;
+ if ((!dc)||(!d)) return childNode;
+ if (dc->pParent) { if ((detachFromParent(dc)<=pos)&&(dc->pParent==d)) pos--; } else dc->ref_count++;
+ dc->pParent=d;
+// int nc=d->nChild;
+// d->pChild=(XMLNode*)myRealloc(d->pChild,(nc+1),memoryIncrease,sizeof(XMLNode));
+ d->pChild=(XMLNode*)addToOrder(0,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild);
+ d->pChild[pos].d=dc;
+ d->nChild++;
+ return childNode;
+}
+
+void XMLNode::deleteAttribute(int i)
+{
+ if ((!d)||(i<0)||(i>=d->nAttribute)) return;
+ d->nAttribute--;
+ XMLAttribute *p=d->pAttribute+i;
+ free((void*)p->lpszName);
+ if (p->lpszValue) free((void*)p->lpszValue);
+ if (d->nAttribute) memmove(p,p+1,(d->nAttribute-i)*sizeof(XMLAttribute)); else { free(p); d->pAttribute=NULL; }
+}
+
+void XMLNode::deleteAttribute(XMLAttribute *a){ if (a) deleteAttribute(a->lpszName); }
+void XMLNode::deleteAttribute(XMLCSTR lpszName)
+{
+ int j=0;
+ getAttribute(lpszName,&j);
+ if (j) deleteAttribute(j-1);
+}
+
+XMLAttribute *XMLNode::updateAttribute_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,int i)
+{
+ if (!d) return NULL;
+ if (i>=d->nAttribute)
+ {
+ if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue);
+ return NULL;
+ }
+ XMLAttribute *p=d->pAttribute+i;
+ if (p->lpszValue&&p->lpszValue!=lpszNewValue) free((void*)p->lpszValue);
+ p->lpszValue=lpszNewValue;
+ if (lpszNewName&&p->lpszName!=lpszNewName) { free((void*)p->lpszName); p->lpszName=lpszNewName; };
+ return p;
+}
+
+XMLAttribute *XMLNode::updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute)
+{
+ if (oldAttribute) return updateAttribute_WOSD(newAttribute->lpszValue,newAttribute->lpszName,oldAttribute->lpszName);
+ return addAttribute_WOSD(newAttribute->lpszName,newAttribute->lpszValue);
+}
+
+XMLAttribute *XMLNode::updateAttribute_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName)
+{
+ int j=0;
+ getAttribute(lpszOldName,&j);
+ if (j) return updateAttribute_WOSD(lpszNewValue,lpszNewName,j-1);
+ else
+ {
+ if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue);
+ else return addAttribute_WOSD(stringDup(lpszOldName),lpszNewValue);
+ }
+}
+
+int XMLNode::indexText(XMLCSTR lpszValue) const
+{
+ if (!d) return -1;
+ int i,l=d->nText;
+ if (!lpszValue) { if (l) return 0; return -1; }
+ XMLCSTR *p=d->pText;
+ for (i=0; i<l; i++) if (lpszValue==p[i]) return i;
+ return -1;
+}
+
+void XMLNode::deleteText(int i)
+{
+ if ((!d)||(i<0)||(i>=d->nText)) return;
+ d->nText--;
+ XMLCSTR *p=d->pText+i;
+ free((void*)*p);
+ if (d->nText) memmove(p,p+1,(d->nText-i)*sizeof(XMLCSTR)); else { free(p); d->pText=NULL; }
+ removeOrderElement(d,eNodeText,i);
+}
+
+void XMLNode::deleteText(XMLCSTR lpszValue) { deleteText(indexText(lpszValue)); }
+
+XMLCSTR XMLNode::updateText_WOSD(XMLCSTR lpszNewValue, int i)
+{
+ if (!d) return NULL;
+ if (i>=d->nText) return addText_WOSD(lpszNewValue);
+ XMLCSTR *p=d->pText+i;
+ if (*p!=lpszNewValue) { free((void*)*p); *p=lpszNewValue; }
+ return lpszNewValue;
+}
+
+XMLCSTR XMLNode::updateText_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
+{
+ if (!d) return NULL;
+ int i=indexText(lpszOldValue);
+ if (i>=0) return updateText_WOSD(lpszNewValue,i);
+ return addText_WOSD(lpszNewValue);
+}
+
+void XMLNode::deleteClear(int i)
+{
+ if ((!d)||(i<0)||(i>=d->nClear)) return;
+ d->nClear--;
+ XMLClear *p=d->pClear+i;
+ free((void*)p->lpszValue);
+ if (d->nClear) memmove(p,p+1,(d->nText-i)*sizeof(XMLClear)); else { free(p); d->pClear=NULL; }
+ removeOrderElement(d,eNodeClear,i);
+}
+
+int XMLNode::indexClear(XMLCSTR lpszValue) const
+{
+ if (!d) return -1;
+ int i,l=d->nClear;
+ if (!lpszValue) { if (l) return 0; return -1; }
+ XMLClear *p=d->pClear;
+ for (i=0; i<l; i++) if (lpszValue==p[i].lpszValue) return i;
+ return -1;
+}
+
+void XMLNode::deleteClear(XMLCSTR lpszValue) { deleteClear(indexClear(lpszValue)); }
+void XMLNode::deleteClear(XMLClear *a) { if (a) deleteClear(a->lpszValue); }
+
+XMLClear *XMLNode::updateClear_WOSD(XMLCSTR lpszNewContent, int i)
+{
+ if (!d) return NULL;
+ if (i>=d->nClear)
+ {
+ return addClear_WOSD(XMLClearTags[0].lpszOpen,lpszNewContent,XMLClearTags[0].lpszClose);
+ }
+ XMLClear *p=d->pClear+i;
+ if (lpszNewContent!=p->lpszValue) { free((void*)p->lpszValue); p->lpszValue=lpszNewContent; }
+ return p;
+}
+
+XMLClear *XMLNode::updateClear_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
+{
+ if (!d) return NULL;
+ int i=indexClear(lpszOldValue);
+ if (i>=0) return updateClear_WOSD(lpszNewValue,i);
+ return addClear_WOSD(lpszNewValue,XMLClearTags[0].lpszOpen,XMLClearTags[0].lpszClose);
+}
+
+XMLClear *XMLNode::updateClear_WOSD(XMLClear *newP,XMLClear *oldP)
+{
+ if (oldP) return updateClear_WOSD(newP->lpszValue,oldP->lpszValue);
+ return NULL;
+}
+
+XMLNode& XMLNode::operator=( const XMLNode& A )
+{
+ // shallow copy
+ if (this != &A)
+ {
+ deleteNodeContent();
+ d=A.d;
+ if (d) (d->ref_count) ++ ;
+ }
+ return *this;
+}
+
+XMLNode::XMLNode(const XMLNode &A)
+{
+ // shallow copy
+ d=A.d;
+ if (d) (d->ref_count)++ ;
+}
+
+int XMLNode::nChildNode(XMLCSTR name) const
+{
+ if (!d) return 0;
+ int i,j=0,n=d->nChild;
+ XMLNode *pc=d->pChild;
+ for (i=0; i<n; i++)
+ {
+ if (_tcsicmp(pc->d->lpszName, name)==0) j++;
+ pc++;
+ }
+ return j;
+}
+
+XMLNode XMLNode::getChildNode(XMLCSTR name, int *j) const
+{
+ if (!d) return emptyXMLNode;
+ int i=0,n=d->nChild;
+ if (j) i=*j;
+ XMLNode *pc=d->pChild+i;
+ for (; i<n; i++)
+ {
+ if (_tcsicmp(pc->d->lpszName, name)==0)
+ {
+ if (j) *j=i+1;
+ return *pc;
+ }
+ pc++;
+ }
+ return emptyXMLNode;
+}
+
+XMLNode XMLNode::getChildNode(XMLCSTR name, int j) const
+{
+ if (!d) return emptyXMLNode;
+ int i=0;
+ while (j-->0) getChildNode(name,&i);
+ return getChildNode(name,&i);
+}
+
+int XMLNode::positionOfText (int i) const { if (i>=d->nText ) i=d->nText-1; return findPosition(d,i,eNodeText ); }
+int XMLNode::positionOfClear (int i) const { if (i>=d->nClear) i=d->nClear-1; return findPosition(d,i,eNodeClear); }
+int XMLNode::positionOfChildNode(int i) const { if (i>=d->nChild) i=d->nChild-1; return findPosition(d,i,eNodeChild); }
+int XMLNode::positionOfText (XMLCSTR lpszValue) const { return positionOfText (indexText (lpszValue)); }
+int XMLNode::positionOfClear(XMLCSTR lpszValue) const { return positionOfClear(indexClear(lpszValue)); }
+int XMLNode::positionOfClear(XMLClear *a) const { if (a) return positionOfClear(a->lpszValue); return positionOfClear(); }
+int XMLNode::positionOfChildNode(XMLNode x) const
+{
+ if ((!d)||(!x.d)) return -1;
+ XMLNodeData *dd=x.d;
+ XMLNode *pc=d->pChild;
+ int i=d->nChild;
+ while (i--) if (pc[i].d==dd) return findPosition(d,i,eNodeChild);
+ return -1;
+}
+int XMLNode::positionOfChildNode(XMLCSTR name, int count) const
+{
+ if (!name) return positionOfChildNode(count);
+ int j=0;
+ do { getChildNode(name,&j); if (j<0) return -1; } while (count--);
+ return findPosition(d,j-1,eNodeChild);
+}
+
+XMLNode XMLNode::getChildNodeWithAttribute(XMLCSTR name,XMLCSTR attributeName,XMLCSTR attributeValue, int *k) const
+{
+ int i=0,j;
+ if (k) i=*k;
+ XMLNode x;
+ XMLCSTR t;
+ do
+ {
+ x=getChildNode(name,&i);
+ if (!x.isEmpty())
+ {
+ if (attributeValue)
+ {
+ j=0;
+ do
+ {
+ t=x.getAttribute(attributeName,&j);
+ if (t&&(_tcsicmp(attributeValue,t)==0)) { if (k) *k=i+1; return x; }
+ } while (t);
+ } else
+ {
+ if (x.isAttributeSet(attributeName)) { if (k) *k=i+1; return x; }
+ }
+ }
+ } while (!x.isEmpty());
+ return emptyXMLNode;
+}
+
+// Find an attribute on an node.
+XMLCSTR XMLNode::getAttribute(XMLCSTR lpszAttrib, int *j) const
+{
+ if (!d) return NULL;
+ int i=0,n=d->nAttribute;
+ if (j) i=*j;
+ XMLAttribute *pAttr=d->pAttribute+i;
+ for (; i<n; i++)
+ {
+ if (_tcsicmp(pAttr->lpszName, lpszAttrib)==0)
+ {
+ if (j) *j=i+1;
+ return pAttr->lpszValue;
+ }
+ pAttr++;
+ }
+ return NULL;
+}
+
+char XMLNode::isAttributeSet(XMLCSTR lpszAttrib) const
+{
+ if (!d) return FALSE;
+ int i,n=d->nAttribute;
+ XMLAttribute *pAttr=d->pAttribute;
+ for (i=0; i<n; i++)
+ {
+ if (_tcsicmp(pAttr->lpszName, lpszAttrib)==0)
+ {
+ return TRUE;
+ }
+ pAttr++;
+ }
+ return FALSE;
+}
+
+XMLCSTR XMLNode::getAttribute(XMLCSTR name, int j) const
+{
+ if (!d) return NULL;
+ int i=0;
+ while (j-->0) getAttribute(name,&i);
+ return getAttribute(name,&i);
+}
+
+XMLNodeContents XMLNode::enumContents(int i) const
+{
+ XMLNodeContents c;
+ if (!d) { c.type=eNodeNULL; return c; }
+ if (i<d->nAttribute)
+ {
+ c.type=eNodeAttribute;
+ c.attrib=d->pAttribute[i];
+ return c;
+ }
+ i-=d->nAttribute;
+ c.type=(XMLElementType)(d->pOrder[i]&3);
+ i=(d->pOrder[i])>>2;
+ switch (c.type)
+ {
+ case eNodeChild: c.child = d->pChild[i]; break;
+ case eNodeText: c.text = d->pText[i]; break;
+ case eNodeClear: c.clear = d->pClear[i]; break;
+ default: break;
+ }
+ return c;
+}
+
+XMLCSTR XMLNode::getName() const { if (!d) return NULL; return d->lpszName; }
+int XMLNode::nText() const { if (!d) return 0; return d->nText; }
+int XMLNode::nChildNode() const { if (!d) return 0; return d->nChild; }
+int XMLNode::nAttribute() const { if (!d) return 0; return d->nAttribute; }
+int XMLNode::nClear() const { if (!d) return 0; return d->nClear; }
+int XMLNode::nElement() const { if (!d) return 0; return d->nAttribute+d->nChild+d->nText+d->nClear; }
+XMLClear XMLNode::getClear (int i) const { if ((!d)||(i>=d->nClear )) return emptyXMLClear; return d->pClear[i]; }
+XMLAttribute XMLNode::getAttribute (int i) const { if ((!d)||(i>=d->nAttribute)) return emptyXMLAttribute; return d->pAttribute[i]; }
+XMLCSTR XMLNode::getAttributeName (int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszName; }
+XMLCSTR XMLNode::getAttributeValue(int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszValue; }
+XMLCSTR XMLNode::getText (int i) const { if ((!d)||(i>=d->nText )) return NULL; return d->pText[i]; }
+XMLNode XMLNode::getChildNode (int i) const { if ((!d)||(i>=d->nChild )) return emptyXMLNode; return d->pChild[i]; }
+XMLNode XMLNode::getParentNode ( ) const { if ((!d)||(!d->pParent )) return emptyXMLNode; return XMLNode(d->pParent); }
+char XMLNode::isDeclaration ( ) const { if (!d) return 0; return d->isDeclaration; }
+char XMLNode::isEmpty ( ) const { return (d==NULL); }
+
+XMLNode XMLNode::addChild(XMLCSTR lpszName, char isDeclaration, int pos)
+ { return addChild_priv(0,stringDup(lpszName),isDeclaration,pos); }
+XMLNode XMLNode::addChild_WOSD(XMLCSTR lpszName, char isDeclaration, int pos)
+ { return addChild_priv(0,lpszName,isDeclaration,pos); }
+XMLAttribute *XMLNode::addAttribute(XMLCSTR lpszName, XMLCSTR lpszValue)
+ { return addAttribute_priv(0,stringDup(lpszName),stringDup(lpszValue)); }
+XMLAttribute *XMLNode::addAttribute_WOSD(XMLCSTR lpszName, XMLCSTR lpszValuev)
+ { return addAttribute_priv(0,lpszName,lpszValuev); }
+XMLCSTR XMLNode::addText(XMLCSTR lpszValue, int pos)
+ { return addText_priv(0,stringDup(lpszValue),pos); }
+XMLCSTR XMLNode::addText_WOSD(XMLCSTR lpszValue, int pos)
+ { return addText_priv(0,lpszValue,pos); }
+XMLClear *XMLNode::addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos)
+ { return addClear_priv(0,stringDup(lpszValue),lpszOpen,lpszClose,pos); }
+XMLClear *XMLNode::addClear_WOSD(XMLCSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos)
+ { return addClear_priv(0,lpszValue,lpszOpen,lpszClose,pos); }
+XMLCSTR XMLNode::updateName(XMLCSTR lpszName)
+ { return updateName_WOSD(stringDup(lpszName)); }
+XMLAttribute *XMLNode::updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute)
+ { return updateAttribute_WOSD(stringDup(newAttribute->lpszValue),stringDup(newAttribute->lpszName),oldAttribute->lpszName); }
+XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,int i)
+ { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),i); }
+XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName)
+ { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),lpszOldName); }
+XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, int i)
+ { return updateText_WOSD(stringDup(lpszNewValue),i); }
+XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
+ { return updateText_WOSD(stringDup(lpszNewValue),lpszOldValue); }
+XMLClear *XMLNode::updateClear(XMLCSTR lpszNewContent, int i)
+ { return updateClear_WOSD(stringDup(lpszNewContent),i); }
+XMLClear *XMLNode::updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
+ { return updateClear_WOSD(stringDup(lpszNewValue),lpszOldValue); }
+XMLClear *XMLNode::updateClear(XMLClear *newP,XMLClear *oldP)
+ { return updateClear_WOSD(stringDup(newP->lpszValue),oldP->lpszValue); }
+
+void XMLNode::setGlobalOptions(char _guessUnicodeChars, char _strictUTF8Parsing, char _dropWhiteSpace)
+{
+ guessUnicodeChars=_guessUnicodeChars; dropWhiteSpace=_dropWhiteSpace; strictUTF8Parsing=_strictUTF8Parsing;
+#ifndef _XMLUNICODE
+ if (_strictUTF8Parsing) XML_ByteTable=XML_utf8ByteTable; else XML_ByteTable=XML_asciiByteTable;
+#endif
+}
+
+char XMLNode::guessUTF8ParsingParameterValue(void *buf,int l, char useXMLEncodingAttribute)
+{
+#ifdef _XMLUNICODE
+ return 0;
+#else
+ if (l<25) return 0;
+ if (myIsTextUnicode(buf,l)) return 0;
+ unsigned char *b=(unsigned char*)buf;
+ if ((b[0]==0xef)&&(b[1]==0xbb)&&(b[2]==0xbf)) return 1;
+
+ // Match utf-8 model ?
+ int i=0;
+ while (i<l)
+ switch (XML_utf8ByteTable[b[i]])
+ {
+ case 4: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) return 0; // 10bbbbbb ?
+ case 3: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) return 0; // 10bbbbbb ?
+ case 2: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) return 0; // 10bbbbbb ?
+ case 1: i++; break;
+ case 0: i=l;
+ }
+ if (!useXMLEncodingAttribute) return 1;
+ // if encoding is specified and different from utf-8 than it's non-utf8
+ // otherwise it's utf-8
+ char bb[201];
+ l=mmin(l,200);
+ memcpy(bb,buf,l); // copy buf into bb to be able to do "bb[l]=0"
+ bb[l]=0;
+ b=(unsigned char*)strstr(bb,"encoding");
+ if (!b) return 1;
+ b+=8; while XML_isSPACECHAR(*b) b++; if (*b!='=') return 1;
+ b++; while XML_isSPACECHAR(*b) b++; if ((*b!='\'')&&(*b!='"')) return 1;
+ b++; while XML_isSPACECHAR(*b) b++; if ((_strnicmp((char*)b,"utf-8",5)==0)||
+ (_strnicmp((char*)b,"utf8",4)==0)) return 1;
+ return 0;
+#endif
+}
+#undef XML_isSPACECHAR
+
+//////////////////////////////////////////////////////////
+// Here starts the base64 conversion functions. //
+//////////////////////////////////////////////////////////
+
+static const char base64Fillchar = _T('='); // used to mark partial words at the end
+
+// this lookup table defines the base64 encoding
+XMLCSTR base64EncodeTable=_T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
+
+// Decode Table gives the index of any valid base64 character in the Base64 table]
+// 96: '=' - 97: space char - 98: illegal char - 99: end of string
+const unsigned char base64DecodeTable[] = {
+ 99,98,98,98,98,98,98,98,98,97, 97,98,98,97,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //00 -29
+ 98,98,97,98,98,98,98,98,98,98, 98,98,98,62,98,98,98,63,52,53, 54,55,56,57,58,59,60,61,98,98, //30 -59
+ 98,96,98,98,98, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24, //60 -89
+ 25,98,98,98,98,98,98,26,27,28, 29,30,31,32,33,34,35,36,37,38, 39,40,41,42,43,44,45,46,47,48, //90 -119
+ 49,50,51,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //120 -149
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //150 -179
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //180 -209
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //210 -239
+ 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98 //240 -255
+};
+
+XMLParserBase64Tool::~XMLParserBase64Tool(){ freeBuffer(); }
+
+void XMLParserBase64Tool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; }
+
+int XMLParserBase64Tool::encodeLength(int inlen, char formatted)
+{
+ unsigned int i=((inlen-1)/3*4+4+1);
+ if (formatted) i+=inlen/54;
+ return i;
+}
+
+XMLSTR XMLParserBase64Tool::encode(unsigned char *inbuf, unsigned int inlen, char formatted)
+{
+ int i=encodeLength(inlen,formatted),k=17,eLen=inlen/3,j;
+ alloc(i*sizeof(XMLCHAR));
+ XMLSTR curr=(XMLSTR)buf;
+ for(i=0;i<eLen;i++)
+ {
+ // Copy next three bytes into lower 24 bits of int, paying attention to sign.
+ j=(inbuf[0]<<16)|(inbuf[1]<<8)|inbuf[2]; inbuf+=3;
+ // Encode the int into four chars
+ *(curr++)=base64EncodeTable[ j>>18 ];
+ *(curr++)=base64EncodeTable[(j>>12)&0x3f];
+ *(curr++)=base64EncodeTable[(j>> 6)&0x3f];
+ *(curr++)=base64EncodeTable[(j )&0x3f];
+ if (formatted) { if (!k) { *(curr++)=_T('\n'); k=18; } k--; }
+ }
+ eLen=inlen-eLen*3; // 0 - 2.
+ if (eLen==1)
+ {
+ *(curr++)=base64EncodeTable[ inbuf[0]>>2 ];
+ *(curr++)=base64EncodeTable[(inbuf[0]<<4)&0x3F];
+ *(curr++)=base64Fillchar;
+ *(curr++)=base64Fillchar;
+ } else if (eLen==2)
+ {
+ j=(inbuf[0]<<8)|inbuf[1];
+ *(curr++)=base64EncodeTable[ j>>10 ];
+ *(curr++)=base64EncodeTable[(j>> 4)&0x3f];
+ *(curr++)=base64EncodeTable[(j<< 2)&0x3f];
+ *(curr++)=base64Fillchar;
+ }
+ *(curr++)=0;
+ return (XMLSTR)buf;
+}
+
+unsigned int XMLParserBase64Tool::decodeSize(XMLCSTR data,XMLError *xe)
+{
+ if (xe) *xe=eXMLErrorNone;
+ int size=0;
+ unsigned char c;
+ //skip any extra characters (e.g. newlines or spaces)
+ while (*data)
+ {
+#ifdef _XMLUNICODE
+ if (*data>255) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
+#endif
+ c=base64DecodeTable[(unsigned char)(*data)];
+ if (c<97) size++;
+ else if (c==98) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
+ data++;
+ }
+ if (xe&&(size%4!=0)) *xe=eXMLErrorBase64DataSizeIsNotMultipleOf4;
+ if (size==0) return 0;
+ do { data--; size--; } while(*data==base64Fillchar); size++;
+ return (unsigned int)((size*3)/4);
+}
+
+unsigned char XMLParserBase64Tool::decode(XMLCSTR data, unsigned char *buf, int len, XMLError *xe)
+{
+ if (xe) *xe=eXMLErrorNone;
+ int i=0,p=0;
+ unsigned char d,c;
+ for(;;)
+ {
+
+#ifdef _XMLUNICODE
+#define BASE64DECODE_READ_NEXT_CHAR(c) \
+ do { \
+ if (data[i]>255){ c=98; break; } \
+ c=base64DecodeTable[(unsigned char)data[i++]]; \
+ }while (c==97); \
+ if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
+#else
+#define BASE64DECODE_READ_NEXT_CHAR(c) \
+ do { c=base64DecodeTable[(unsigned char)data[i++]]; }while (c==97); \
+ if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
+#endif
+
+ BASE64DECODE_READ_NEXT_CHAR(c)
+ if (c==99) { return 2; }
+ if (c==96)
+ {
+ if (p==(int)len) return 2;
+ if (xe) *xe=eXMLErrorBase64DecodeTruncatedData;
+ return 1;
+ }
+
+ BASE64DECODE_READ_NEXT_CHAR(d)
+ if ((d==99)||(d==96)) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ if (p==(int)len) { if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall; return 0; }
+ buf[p++]=(c<<2)|((d>>4)&0x3);
+
+ BASE64DECODE_READ_NEXT_CHAR(c)
+ if (c==99) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ if (p==(int)len)
+ {
+ if (c==96) return 2;
+ if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall;
+ return 0;
+ }
+ if (c==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ buf[p++]=((d<<4)&0xf0)|((c>>2)&0xf);
+
+ BASE64DECODE_READ_NEXT_CHAR(d)
+ if (d==99 ) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ if (p==(int)len)
+ {
+ if (d==96) return 2;
+ if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall;
+ return 0;
+ }
+ if (d==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
+ buf[p++]=((c<<6)&0xc0)|d;
+ }
+}
+#undef BASE64DECODE_READ_NEXT_CHAR
+
+void XMLParserBase64Tool::alloc(int newsize)
+{
+ if ((!buf)&&(newsize)) { buf=malloc(newsize); buflen=newsize; return; }
+ if (newsize>buflen) { buf=realloc(buf,newsize); buflen=newsize; }
+}
+
+unsigned char *XMLParserBase64Tool::decode(XMLCSTR data, int *outlen, XMLError *xe)
+{
+ if (xe) *xe=eXMLErrorNone;
+ unsigned int len=decodeSize(data,xe);
+ if (outlen) *outlen=len;
+ if (!len) return NULL;
+ alloc(len+1);
+ if(!decode(data,(unsigned char*)buf,len,xe)){ return NULL; }
+ return (unsigned char*)buf;
+}
+
--- /dev/null
+/**
+ ****************************************************************************
+ * <P> XML.c - implementation file for basic XML parser written in ANSI C++
+ * for portability. It works by using recursion and a node tree for breaking
+ * down the elements of an XML document. </P>
+ *
+ * @version V2.23
+ * @author Frank Vanden Berghen
+ *
+ * BSD license:
+ * Copyright (c) 2002, Frank Vanden Berghen
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Frank Vanden Berghen nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************
+ */
+#ifndef __INCLUDE_XML_NODE__
+#define __INCLUDE_XML_NODE__
+
+#include <stdlib.h>
+
+#ifdef _UNICODE
+// If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters).
+// This is useful when you get error messages like:
+// 'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *'
+// The _XMLUNICODE preprocessor variable force the XMLParser library into either utf16/32-mode (the proprocessor variable
+// must be defined) or utf8-mode(the pre-processor variable must be undefined).
+#define _XMLUNICODE
+#endif
+
+#if defined(WIN32) || defined(UNDER_CE)
+// comment the next line if you are under windows and the compiler is not Microsoft Visual Studio (6.0 or .NET)
+#define _XMLWINDOWS
+#endif
+
+#ifdef DLLENTRY
+#undef DLLENTRY
+#endif
+#ifdef _USE_XMLPARSER_DLL
+#ifdef _DLL_EXPORTS_
+#define DLLENTRY __declspec(dllexport)
+#else
+#define DLLENTRY __declspec(dllimport)
+#endif
+#else
+#define DLLENTRY
+#endif
+
+// uncomment the next line if you want no support for wchar_t* (no need for the <wchar.h> or <tchar.h> libraries anymore to compile)
+//#define XML_NO_WIDE_CHAR
+
+#ifdef XML_NO_WIDE_CHAR
+#undef _XMLWINDOWS
+#undef _XMLUNICODE
+#endif
+
+#ifdef _XMLWINDOWS
+#include <tchar.h>
+#else
+#define DLLENTRY
+#ifndef XML_NO_WIDE_CHAR
+#include <wchar.h> // to have 'wcsrtombs' for ANSI version
+ // to have 'mbsrtowcs' for UNICODE version
+#endif
+#endif
+
+// Some common types for char set portable code
+#ifdef _XMLUNICODE
+ #ifndef _T
+ #define _T(c) L ## c
+ #endif
+ #define XMLCSTR const wchar_t *
+ #define XMLSTR wchar_t *
+ #define XMLCHAR wchar_t
+#else
+ #ifndef _T
+ #define _T(c) c
+ #endif
+ #define XMLCSTR const char *
+ #define XMLSTR char *
+ #define XMLCHAR char
+#endif
+#ifndef FALSE
+ #define FALSE 0
+#endif /* FALSE */
+#ifndef TRUE
+ #define TRUE 1
+#endif /* TRUE */
+
+
+// Enumeration for XML parse errors.
+typedef enum XMLError
+{
+ eXMLErrorNone = 0,
+ eXMLErrorMissingEndTag,
+ eXMLErrorEmpty,
+ eXMLErrorFirstNotStartTag,
+ eXMLErrorMissingTagName,
+ eXMLErrorMissingEndTagName,
+ eXMLErrorNoMatchingQuote,
+ eXMLErrorUnmatchedEndTag,
+ eXMLErrorUnmatchedEndClearTag,
+ eXMLErrorUnexpectedToken,
+ eXMLErrorInvalidTag,
+ eXMLErrorNoElements,
+ eXMLErrorFileNotFound,
+ eXMLErrorFirstTagNotFound,
+ eXMLErrorUnknownCharacterEntity,
+ eXMLErrorCharConversionError,
+ eXMLErrorCannotOpenWriteFile,
+ eXMLErrorCannotWriteFile,
+
+ eXMLErrorBase64DataSizeIsNotMultipleOf4,
+ eXMLErrorBase64DecodeIllegalCharacter,
+ eXMLErrorBase64DecodeTruncatedData,
+ eXMLErrorBase64DecodeBufferTooSmall
+} XMLError;
+
+// Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents
+typedef enum XMLElementType
+{
+ eNodeChild=0,
+ eNodeAttribute=1,
+ eNodeText=2,
+ eNodeClear=3,
+ eNodeNULL=4
+} XMLElementType;
+
+// Structure used to obtain error details if the parse fails.
+typedef struct XMLResults
+{
+ enum XMLError error;
+ int nLine,nColumn;
+} XMLResults;
+
+// Structure for XML clear (unformatted) node (usually comments)
+typedef struct {
+ XMLCSTR lpszValue; XMLCSTR lpszOpenTag; XMLCSTR lpszCloseTag;
+} XMLClear;
+
+// Structure for XML attribute.
+typedef struct {
+ XMLCSTR lpszName; XMLCSTR lpszValue;
+} XMLAttribute;
+
+// Structure for XML clear tags.
+typedef struct {
+ XMLCSTR lpszOpen; int openTagLen; XMLCSTR lpszClose;
+} ALLXMLClearTag;
+
+struct XMLNodeContents;
+
+typedef struct DLLENTRY XMLNode
+{
+ private:
+
+ struct XMLNodeDataTag;
+
+ // protected constructors: use one of these four methods to get your first instance of XMLNode:
+ // - parseString
+ // - parseFile
+ // - openFileHelper
+ // - createXMLTopNode
+ XMLNode(struct XMLNodeDataTag *pParent, XMLCSTR lpszName, char isDeclaration);
+ XMLNode(struct XMLNodeDataTag *p);
+
+ public:
+
+ // You can create your first instance of XMLNode with these 4 functions:
+ // (see complete explanation of parameters below)
+
+ static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE);
+ static XMLNode parseString (XMLCSTR lpXMLString, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
+ static XMLNode parseFile (XMLCSTR filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
+ static XMLNode openFileHelper(XMLCSTR filename, XMLCSTR tag=NULL );
+
+ // The tag parameter should be the name of the first tag inside the XML file.
+ // If the tag parameter is omitted, the 3 functions return a node that represents
+ // the head of the xml document including the declaration term (<? ... ?>).
+
+ // The "openFileHelper" reports to the screen all the warnings & errors that occurred during
+ // parsing of the XML file. Since each application has its own way to report and deal with errors,
+ // you should rather use the "parseFile" function to parse XML files and program yourself thereafter
+ // an "error reporting" tailored for your needs (instead of using the very crude "error reporting"
+ // mechanism included inside the "openFileHelper" function).
+
+ // If the XML document is corrupted:
+ // * The "openFileHelper" method will:
+ // - display an error message on the console (or inside a messageBox for windows).
+ // - stop execution (exit).
+ // I suggest that you write your own "openFileHelper" method tailored to your needs.
+ // * The 2 other methods will initialize the "pResults" variable with some information that
+ // can be used to trace the error.
+ // * If you still want to parse the file, you can use the APPROXIMATE_PARSING option as
+ // explained inside the note at the beginning of the "xmlParser.cpp" file.
+ // You can have a user-friendly explanation of the parsing error with this function:
+ static XMLCSTR getError(XMLError error);
+ static XMLCSTR getVersion();
+ static ALLXMLClearTag* getClearTagTable();
+
+ XMLCSTR getName() const; // name of the node
+ XMLCSTR getText(int i=0) const; // return ith text field
+ int nText() const; // nbr of text field
+ XMLNode getParentNode() const; // return the parent node
+ XMLNode getChildNode(int i=0) const; // return ith child node
+ XMLNode getChildNode(XMLCSTR name, int i) const; // return ith child node with specific name
+ // (return an empty node if failing)
+ XMLNode getChildNode(XMLCSTR name, int *i=NULL) const; // return next child node with specific name
+ // (return an empty node if failing)
+ XMLNode getChildNodeWithAttribute(XMLCSTR tagName, // return child node with specific name/attribute
+ XMLCSTR attributeName, // (return an empty node if failing)
+ XMLCSTR attributeValue=NULL, //
+ int *i=NULL) const; //
+ int nChildNode(XMLCSTR name) const; // return the number of child node with specific name
+ int nChildNode() const; // nbr of child node
+ XMLAttribute getAttribute(int i=0) const; // return ith attribute
+ XMLCSTR getAttributeName(int i=0) const; // return ith attribute name
+ XMLCSTR getAttributeValue(int i=0) const; // return ith attribute value
+ char isAttributeSet(XMLCSTR name) const; // test if an attribute with a specific name is given
+ XMLCSTR getAttribute(XMLCSTR name, int i) const; // return ith attribute content with specific name
+ // (return a NULL if failing)
+ XMLCSTR getAttribute(XMLCSTR name, int *i=NULL) const; // return next attribute content with specific name
+ // (return a NULL if failing)
+ int nAttribute() const; // nbr of attribute
+ XMLClear getClear(int i=0) const; // return ith clear field (comments)
+ int nClear() const; // nbr of clear field
+ XMLSTR createXMLString(int nFormat=1, int *pnSize=NULL) const; // create XML string starting from current XMLNode
+ // if nFormat==0, no formatting is required
+ // otherwise this returns an user friendly XML string from a
+ // given element with appropriate white spaces and carriage returns.
+ // if pnSize is given it returns the size in character of the string.
+ XMLError writeToFile(XMLCSTR filename, const char *encoding=NULL, char nFormat=1) const;
+ // save the content of an xmlNode inside a file.
+ // the nFormat parameter has the same meaning as in the
+ // createXMLString function. If "strictUTF8Parsing=1", the
+ // the encoding parameter is ignored and always set to
+ // "utf-8". If "_XMLUNICODE=1", the encoding parameter is
+ // ignored and always set to "utf-16".
+ XMLNodeContents enumContents(int i) const; // enumerate all the different contents (attribute,child,text,
+ // clear) of the current XMLNode. The order is reflecting
+ // the order of the original file/string.
+ // NOTE: 0 <= i < nElement();
+ int nElement() const; // nbr of different contents for current node
+ char isEmpty() const; // is this node Empty?
+ char isDeclaration() const; // is this node a declaration <? .... ?>
+
+// to allow shallow/fast copy:
+ ~XMLNode();
+ XMLNode(const XMLNode &A);
+ XMLNode& operator=( const XMLNode& A );
+
+ XMLNode(): d(NULL){};
+ static XMLNode emptyXMLNode;
+ static XMLClear emptyXMLClear;
+ static XMLAttribute emptyXMLAttribute;
+
+ // The following functions allows you to create from scratch (or update) a XMLNode structure
+ // Start by creating your top node with the "createXMLTopNode" function and then add new nodes with the "addChild" function.
+ // The parameter 'pos' gives the position where the childNode, the text or the XMLClearTag will be inserted.
+ // The default value (pos=-1) inserts at the end. The value (pos=0) insert at the beginning (Insertion at the beginning is slower than at the end).
+ // REMARK: 0 <= pos < nChild()+nText()+nClear()
+ XMLNode addChild(XMLCSTR lpszName, char isDeclaration=FALSE, int pos=-1);
+ XMLAttribute *addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev);
+ XMLCSTR addText(XMLCSTR lpszValue, int pos=-1);
+ XMLClear *addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, int pos=-1);
+ // default values: lpszOpen=XMLNode::getClearTagTable()->lpszOpen;
+ // lpszClose=XMLNode::getClearTagTable()->lpszClose;
+ XMLNode addChild(XMLNode nodeToAdd, int pos=-1); // If the "nodeToAdd" has some parents, it will be detached
+ // from it's parents before being attached to the current XMLNode
+ // Some update functions:
+ XMLCSTR updateName(XMLCSTR lpszName); // change node's name
+ XMLAttribute *updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute); // if the attribute to update is missing, a new one will be added
+ XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0); // if the attribute to update is missing, a new one will be added
+ XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName); // set lpszNewName=NULL if you don't want to change the name of the attribute
+ // if the attribute to update is missing, a new one will be added
+ XMLCSTR updateText(XMLCSTR lpszNewValue, int i=0); // if the text to update is missing, a new one will be added
+ XMLCSTR updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue); // if the text to update is missing, a new one will be added
+ XMLClear *updateClear(XMLCSTR lpszNewContent, int i=0); // if the clearTag to update is missing, a new one will be added
+ XMLClear *updateClear(XMLClear *newP,XMLClear *oldP); // if the clearTag to update is missing, a new one will be added
+ XMLClear *updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue); // if the clearTag to update is missing, a new one will be added
+
+ // Some deletion functions:
+ void deleteNodeContent(char force=0); // delete the content of this XMLNode and the subtree.
+ // if force=0, while (references to this node still exist), no memory free occurs
+ // if force=1, always delete the content of this XMLNode and the subtree and free associated memory
+ void deleteAttribute(XMLCSTR lpszName);
+ void deleteAttribute(int i=0);
+ void deleteAttribute(XMLAttribute *anAttribute);
+ void deleteText(int i=0);
+ void deleteText(XMLCSTR lpszValue);
+ void deleteClear(int i=0);
+ void deleteClear(XMLClear *p);
+ void deleteClear(XMLCSTR lpszValue);
+
+ // The strings given as parameters for the following add and update methods (all these methods have
+ // a name with the postfix "_WOSD" that means "WithOut String Duplication" ) will be free'd by the
+ // XMLNode class. For example, it means that this is incorrect:
+ // xNode.addText_WOSD("foo");
+ // xNode.updateAttribute_WOSD("#newcolor" ,NULL,"color");
+ // In opposition, this is correct:
+ // xNode.addText("foo");
+ // xNode.addText_WOSD(stringDup("foo"));
+ // xNode.updateAttribute("#newcolor" ,NULL,"color");
+ // xNode.updateAttribute_WOSD(stringDup("#newcolor"),NULL,"color");
+ // Typically, you will never do:
+ // char *b=(char*)malloc(...);
+ // xNode.addText(b);
+ // free(b);
+ // ... but rather:
+ // char *b=(char*)malloc(...);
+ // xNode.addText_WOSD(b);
+ // ('free(b)' is performed by the XMLNode class)
+
+ static XMLNode createXMLTopNode_WOSD(XMLCSTR lpszName, char isDeclaration=FALSE);
+ XMLNode addChild_WOSD(XMLCSTR lpszName, char isDeclaration=FALSE, int pos=-1);
+ XMLAttribute *addAttribute_WOSD(XMLCSTR lpszName, XMLCSTR lpszValue);
+ XMLCSTR addText_WOSD(XMLCSTR lpszValue, int pos=-1);
+ XMLClear *addClear_WOSD(XMLCSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, int pos=-1);
+
+ XMLCSTR updateName_WOSD(XMLCSTR lpszName);
+ XMLAttribute *updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute);
+ XMLAttribute *updateAttribute_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0);
+ XMLAttribute *updateAttribute_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName);
+ XMLCSTR updateText_WOSD(XMLCSTR lpszNewValue, int i=0);
+ XMLCSTR updateText_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);
+ XMLClear *updateClear_WOSD(XMLCSTR lpszNewContent, int i=0);
+ XMLClear *updateClear_WOSD(XMLClear *newP,XMLClear *oldP);
+ XMLClear *updateClear_WOSD(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);
+
+ // These are some useful functions when you want to insert a childNode, a text or a XMLClearTag in the
+ // middle (at a specified position) of a XMLNode tree already constructed. The value returned by these
+ // methods is to be used as last parameter (parameter 'pos') of addChild, addText or addClear.
+ int positionOfText(int i=0) const;
+ int positionOfText(XMLCSTR lpszValue) const;
+ int positionOfClear(int i=0) const;
+ int positionOfClear(XMLCSTR lpszValue) const;
+ int positionOfClear(XMLClear *a) const;
+ int positionOfChildNode(int i=0) const;
+ int positionOfChildNode(XMLNode x) const;
+ int positionOfChildNode(XMLCSTR name, int i=0) const; // return the position of the ith childNode with the specified name
+ // if (name==NULL) return the position of the ith childNode
+
+ // The setGlobalOptions function allows you to change two global parameters that affect string&file
+ // parsing. First of all, you most-probably will never have to change these 2 global parameters.
+ // About the "guessUnicodeChars" parameter:
+ // If "guessUnicodeChars=1" and if this library is compiled in UNICODE mode, then the
+ // "parseFile" and "openFileHelper" functions will test if the file contains ASCII
+ // characters. If this is the case, then the file will be loaded and converted in memory to
+ // UNICODE before being parsed. If "guessUnicodeChars=0", no conversion will
+ // be performed.
+ //
+ // If "guessUnicodeChars=1" and if this library is compiled in ASCII/UTF8 mode, then the
+ // "parseFile" and "openFileHelper" functions will test if the file contains UNICODE
+ // characters. If this is the case, then the file will be loaded and converted in memory to
+ // ASCII/UTF8 before being parsed. If "guessUnicodeChars=0", no conversion will
+ // be performed
+ //
+ // Sometime, it's useful to set "guessUnicodeChars=0" to disable any conversion
+ // because the test to detect the file-type (ASCII/UTF8 or UNICODE) may fail (rarely).
+ //
+ // About the "strictUTF8Parsing" parameter:
+ // If "strictUTF8Parsing=0" then we assume that all characters have the same length of 1 byte.
+ // If "strictUTF8Parsing=1" then the characters have different lengths (from 1 byte to 4 bytes)
+ // depending on the content of the first byte of the character.
+ // About the "dropWhiteSpace" parameter:
+ //
+
+ static void setGlobalOptions(char guessUnicodeChars=1, char strictUTF8Parsing=1, char dropWhiteSpace=1);
+
+ // The next function try to guess if the character encoding is UTF-8. You most-probably will never
+ // have to use this function. It then returns the appropriate value of the global parameter
+ // "strictUTF8Parsing" described above. The guess is based on the content of a buffer of length
+ // "bufLen" bytes that contains the first bytes (minimum 25 bytes; 200 bytes is a good value) of the
+ // file to be parsed. The "openFileHelper" function is using this function to automatically compute
+ // the value of the "strictUTF8Parsing" global parameter. There are several heuristics used to do the
+ // guess. One of the heuristic is based on the "encoding" attribute. The original XML specifications
+ // forbids to use this attribute to do the guess but you can still use it if you set
+ // "useXMLEncodingAttribute" to 1 (this is the default behavior and the behavior of most parsers).
+
+ static char guessUTF8ParsingParameterValue(void *buffer, int bufLen, char useXMLEncodingAttribute=1);
+
+ private:
+
+// these are functions and structures used internally by the XMLNode class (don't bother about them):
+
+ typedef struct XMLNodeDataTag // to allow shallow copy and "intelligent/smart" pointers (automatic delete):
+ {
+ XMLCSTR lpszName; // Element name (=NULL if root)
+ int nChild, // Number of child nodes
+ nText, // Number of text fields
+ nClear, // Number of Clear fields (comments)
+ nAttribute; // Number of attributes
+ char isDeclaration; // Whether node is an XML declaration - '<?xml ?>'
+ struct XMLNodeDataTag *pParent; // Pointer to parent element (=NULL if root)
+ XMLNode *pChild; // Array of child nodes
+ XMLCSTR *pText; // Array of text fields
+ XMLClear *pClear; // Array of clear fields
+ XMLAttribute *pAttribute; // Array of attributes
+ int *pOrder; // order of the child_nodes,text_fields,clear_fields
+ int ref_count; // for garbage collection (smart pointers)
+ } XMLNodeData;
+ XMLNodeData *d;
+
+ char parseClearTag(void *px, ALLXMLClearTag *pa);
+ char maybeAddTxT(void *pa, XMLCSTR tokenPStr);
+ int ParseXMLElement(void *pXML);
+ void *addToOrder(int memInc, int *_pos, int nc, void *p, int size, XMLElementType xtype);
+ int indexText(XMLCSTR lpszValue) const;
+ int indexClear(XMLCSTR lpszValue) const;
+ XMLNode addChild_priv(int,XMLCSTR,char,int);
+ XMLAttribute *addAttribute_priv(int,XMLCSTR,XMLCSTR);
+ XMLCSTR addText_priv(int,XMLCSTR,int);
+ XMLClear *addClear_priv(int,XMLCSTR,XMLCSTR,XMLCSTR,int);
+ static inline int findPosition(XMLNodeData *d, int index, XMLElementType xtype);
+ static int CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat);
+ static int removeOrderElement(XMLNodeData *d, XMLElementType t, int index);
+ static void exactMemory(XMLNodeData *d);
+ static int detachFromParent(XMLNodeData *d);
+} XMLNode;
+
+// This structure is given by the function "enumContents".
+typedef struct XMLNodeContents
+{
+ // This dictates what's the content of the XMLNodeContent
+ enum XMLElementType type;
+ // should be an union to access the appropriate data.
+ // compiler does not allow union of object with constructor... too bad.
+ XMLNode child;
+ XMLAttribute attrib;
+ XMLCSTR text;
+ XMLClear clear;
+
+} XMLNodeContents;
+
+DLLENTRY void free_XMLDLL(void *t); // {free(t);}
+
+// Duplicate (copy in a new allocated buffer) the source string. This is
+// a very handy function when used with all the "XMLNode::*_WOSD" functions.
+// (If (cbData!=0) then cbData is the number of chars to duplicate)
+DLLENTRY XMLSTR stringDup(XMLCSTR source, int cbData=0);
+
+// The 3 following functions are processing strings so that all the characters
+// &,",',<,> are replaced by their XML equivalent: &, ", ', <, >.
+// These 3 functions are useful when creating from scratch an XML file using the
+// "printf", "fprintf", "cout",... functions. If you are creating from scratch an
+// XML file using the provided XMLNode class you cannot use these functions (the
+// XMLNode class does the processing job for you during rendering). The second
+// function ("toXMLStringFast") allows you to re-use the same output buffer
+// for all the conversions so that only a few memory allocations are performed.
+// If the output buffer is too small to contain thee resulting string, it will
+// be enlarged.
+DLLENTRY XMLSTR toXMLString(XMLCSTR source);
+DLLENTRY XMLSTR toXMLStringFast(XMLSTR *destBuffer,int *destSz, XMLCSTR source);
+
+// you should not use this one (there is a possibility of "destination-buffer-overflow"):
+DLLENTRY XMLSTR toXMLString(XMLSTR dest,XMLCSTR source);
+
+// Below is a class that allows you to include any binary data (images, sounds,...)
+// into an XML document using "Base64 encoding". This class is completely
+// separated from the rest of the xmlParser library and can be removed without any problem.
+// To include some binary data into an XML file, you must convert the binary data into
+// standard text (using "encode"). To retrieve the original binary data from the
+// b64-encoded text included inside the XML file use "decode". Alternatively, these
+// functions can also be used to "encrypt/decrypt" some critical data contained inside
+// the XML.
+
+class DLLENTRY XMLParserBase64Tool
+{
+public:
+ XMLParserBase64Tool(): buf(NULL),buflen(0){}
+ ~XMLParserBase64Tool();
+
+ void freeBuffer();
+
+ // returns the length of the base64 string that encodes a data buffer of size inBufLen bytes.
+ // If "formatted" parameter is true, some space will be reserved for a carriage-return every 72 chars.
+ static int encodeLength(int inBufLen, char formatted=0);
+
+ // The "base64Encode" function returns a string containing the base64 encoding of "inByteLen" bytes
+ // from "inByteBuf". If "formatted" parameter is true, then there will be a carriage-return every 72 chars.
+ // The string will be free'd when the XMLParserBase64Tool object is deleted.
+ // All returned strings are sharing the same memory space.
+ XMLSTR encode(unsigned char *inByteBuf, unsigned int inByteLen, char formatted=0);
+
+ // returns the number of bytes which will be decoded from "inString".
+ static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL);
+
+ // returns a pointer to a buffer containing the binary data decoded from "inString"
+ // If "inString" is malformed NULL will be returned
+ // The output buffer will be free'd when the XMLParserBase64Tool object is deleted.
+ // All output buffer are sharing the same memory space.
+ unsigned char* decode(XMLCSTR inString, int *outByteLen=NULL, XMLError *xe=NULL);
+
+ // The next function is deprecated.
+ // decodes data from "inString" to "outByteBuf". You need to provide the size (in byte) of "outByteBuf"
+ // in "inMaxByteOutBuflen". If "outByteBuf" is not large enough or if data is malformed, then "FALSE"
+ // will be returned; otherwise "TRUE".
+ static unsigned char decode(XMLCSTR inString, unsigned char *outByteBuf, int inMaxByteOutBuflen, XMLError *xe=NULL);
+
+private:
+ void *buf;
+ int buflen;
+ void alloc(int newsize);
+};
+
+#undef DLLENTRY
+
+#endif
--- /dev/null
+package dol.visitor.hdsd;
+
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Process;
+import dol.visitor.MapVisitor;
+
+/**
+ * Visitor that is used to generate
+ * a HdS package Makefile for a distributed simulation.
+ */
+public class HdsdMakefileVisitor extends MapVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of the Makefile
+ */
+ public HdsdMakefileVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ * Create a Makefile for the given mapping.
+ *
+ * @param x mapping that needs to be rendered.
+ */
+ public void visitComponent(Mapping x) {
+ try {
+ String filename = _dir + "/" + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ ps.println("CXX = g++");
+ ps.println("CC = g++");
+ ps.println();
+ ps.println("PREPROC_MACROS = -D __DOL_ETHZ_GEN__ -DINCLUDE_PROFILER");
+ ps.println();
+ ps.println("SYSTEMC_INC = -I" + _ui.getSystemCINC());
+ ps.println("SYSTEMC_LIB = " + _ui.getSystemCLIB());
+ ps.println("MY_LIB_INC = -Ilib -Iscd -Isc_wrappers -Iprocesses");
+ ps.println("VPATH = lib:scd:scd/fsm:sc_wrappers:processes");
+ ps.println();
+ ps.println("# append '-rdynamic' for name resolution in exception stack traces");
+ ps.println("# append '-g' for debugging");
+ ps.println("CXXFLAGS = -O0 $(PREPROC_MACROS) $(SYSTEMC_INC) $(MY_LIB_INC)");
+ ps.println("CFLAGS = $(CXXFLAGS)");
+ ps.println();
+
+ // scd library objects
+ ps.println("# scd library objects");
+ ps.println("SCD_OBJS = scd_logging.o scd_exception.o scd_socket.o scd_sock_poller.o \\");
+ ps.println("\tscd_init_listener.o scd_in_connector.o scd_out_connector.o \\");
+ ps.println("\tscd_command.o scd_command_reader.o scd_command_writer.o \\");
+ ps.println("\tscd_simulator.o scd_chan_man.o scd_chan_wrapper.o \\");
+ ps.println("\tscd_cont_man_master.o scd_cont_man_slave.o scd_cont_slave_wrapper.o \\");
+ ps.println("\tscd_rem_fifo_in.o scd_rem_fifo_out.o scd_cont_fsm.o \\");
+ ps.println("\tscd_sts_base.o scd_sts_init.o scd_sts_busy.o scd_sts_idle.o \\");
+ ps.println("\tscd_sts_done.o scd_sts_time_ack.o scd_sts_time.o scd_sts_term_ack.o \\");
+ ps.println("\tscd_sts_terminated.o scd_sts_fail.o scd_sts_failed.o \\");
+ ps.println("\tscd_stm_base.o scd_stm_init.o scd_stm_busy.o scd_stm_idle.o \\");
+ ps.println("\tscd_stm_done.o scd_stm_time_req.o scd_stm_time.o scd_stm_term_req.o \\");
+ ps.println("\tscd_stm_terminate.o scd_stm_terminated.o \\");
+ ps.println("\tscd_stm_fail.o scd_stm_failed.o \\");
+ ps.println("\tscd_stsw_base.o scd_stsw_init.o scd_stsw_busy.o \\");
+ ps.println("\tscd_stsw_idle.o scd_stsw_done.o scd_stsw_time_req.o \\");
+ ps.println("\tscd_stsw_time_ack.o scd_stsw_term_req.o scd_stsw_term_ack.o \\");
+ ps.println("\tscd_stsw_terminate.o scd_stsw_terminated.o \\");
+ ps.println("\tscd_stsw_fail.o scd_stsw_failed.o");
+ ps.println();
+
+ // process objects
+ ps.println("# process objects");
+ ps.print("PROCESS_OBJS = dol.o ");
+ Iterator<Process> i = x.getProcessList().iterator();
+ Set<String> pSet = new HashSet<String>();
+ while (i.hasNext()) {
+ String basename = i.next().getBasename();
+ if (pSet.add(basename))
+ ps.print(basename + "_wrapper.o ");
+ }
+ ps.println();
+ ps.println();
+
+ // target all
+ Iterator<Processor> iter = x.getProcessorList().iterator();
+ String processorList = new String();
+ while (iter.hasNext())
+ {
+ Processor p = iter.next();
+ if (x.getProcessList().isEmpty())
+ continue;
+ processorList += " scd_" + p.getName();
+ }
+ ps.println("all:" + processorList);
+ ps.println();
+
+ // processor targets
+ iter = x.getProcessorList().iterator();
+ while (iter.hasNext())
+ {
+ Processor p = iter.next();
+ if (x.getProcessList().isEmpty())
+ continue;
+ ps.println("scd_" + p.getName() + ": scd_"
+ + p.getName() + ".o $(PROCESS_OBJS)"
+ + " $(SCD_OBJS)");
+ ps.println("\t$(CXX) $(CXXFLAGS) -o $@ $^ $(SYSTEMC_LIB)");
+ ps.println();
+ }
+
+ // clean target
+ ps.println("clean:");
+ ps.println("\t-rm -f *.o core core.* *.core" + processorList);
+
+ } catch (Exception e) {
+ System.out.println("HdsdMakefileVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ protected String _dir = null;
+}
+
--- /dev/null
+package dol.visitor.hdsd;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.Vector;
+
+import dol.datamodel.architecture.Configuration;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.Resource;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+import dol.visitor.ArchiVisitor;
+
+/**
+ * Visitor that generates the main program for one distributed simulator.
+ */
+public class HdsdModuleArchVisitor extends ArchiVisitor {
+
+ /**
+ * Constructor.
+ * @param map mapping of this code generation
+ * @param dir path of this file
+ */
+ public HdsdModuleArchVisitor(Mapping map, String dir) {
+ _map = map;
+ _dir = dir;
+ _channels = new LinkedHashSet<String>();
+ _remInChannels = new LinkedHashSet<String>();
+ _remOutChannels = new LinkedHashSet<String>();
+ _locChannels = new LinkedHashSet<String>();
+ }
+
+ /**
+ *
+ * @param x Processor that needs to be rendered
+ */
+ public void visitComponent(Processor x) {
+
+ // get channels for this processor
+ _getChannels(x);
+
+ try {
+ String filename = _dir + "/" + "scd_" +
+ x.getName() + ".cpp";
+ OutputStream file = new FileOutputStream(filename);
+ _mainPS = new CodePrintStream(file);
+
+ _mainPS.printPrefixln("#include <systemc>");
+ _mainPS.printPrefixln("#include <list>");
+
+ /* begin of profiling: standard i/o file handling routines */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("#include <stdio.h>");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln("#include \"dol_sched_if.h\"");
+ _mainPS.printPrefixln("#include \"simple_fifo.h\"");
+ _mainPS.printPrefixln("#include \"scd_logging.h\"");
+ _mainPS.printPrefixln("#include \"scd_simulator.h\"");
+ _mainPS.printPrefixln("#include \"scd_rem_fifo_in.h\"");
+ _mainPS.printPrefixln("#include \"scd_rem_fifo_out.h\"");
+ _mainPS.println();
+
+ // include process files
+ Iterator<Process> pIt = x.getProcessList().iterator();
+ Vector<String> pList = new Vector<String>();
+ while (pIt.hasNext()) {
+ Process p = pIt.next();
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ _mainPS.printPrefixln("#include \"" + p.getBasename()
+ + "_wrapper.h\"");
+ pList.add(basename);
+ }
+ }
+ _mainPS.println();
+
+ // namespaces
+ _mainPS.printPrefixln("using namespace std;");
+ _mainPS.printPrefixln("using sc_core::sc_module;");
+ _mainPS.printPrefixln("using sc_core::sc_event;");
+ _mainPS.printPrefixln("using sc_core::sc_prim_channel;");
+
+
+ /* begin of profiling: global variables */
+ _mainPS.println();
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("#define PROFILER_OUTPUT_FILENAME "
+ + "\"profile_" + x.getName() + ".txt\"");
+ _mainPS.printPrefixln("FILE *profiler_output_file;");
+ _mainPS.printPrefixln("unsigned int profiler_event_counter;");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.println();
+ _mainPS.printPrefixln("class sc_application : public sc_module ");
+ _mainPS.printLeftBracket();
+
+ _mainPS.printPrefixln("public:");
+ _mainPS.printPrefixln("SC_HAS_PROCESS(sc_application);");
+
+ //declare processes
+ _mainPS.println();
+ pIt = x.getProcessList().iterator();
+ while (pIt.hasNext()) {
+ Process p = pIt.next();
+ _mainPS.printPrefixln(p.getBasename() + "_wrapper "
+ + p.getName() + "_ins"+ ";");
+ _mainPS.printPrefixln("sc_event " + p.getName()
+ + "_event;");
+ }
+ _mainPS.println();
+
+ //define the scheduler
+ _mainPS.printPrefixln("sc_event sched_event;");
+ _mainPS.printPrefixln("list<sc_event* > eventList;");
+ _mainPS.printPrefixln("list<sc_event* >::iterator iter;");
+ _mainPS.println();
+
+ //declare channels
+ _mainPS.println();
+ Iterator<String> cIt;
+ cIt = _locChannels.iterator();
+ while (cIt.hasNext())
+ _mainPS.printPrefixln("fifo " + cIt.next() + "_ins;");
+ cIt = _remInChannels.iterator();
+ while (cIt.hasNext())
+ _mainPS.printPrefixln("scd_rem_fifo_in " + cIt.next() + "_ins;");
+ cIt = _remOutChannels.iterator();
+ while (cIt.hasNext())
+ _mainPS.printPrefixln("scd_rem_fifo_out " + cIt.next() + "_ins;");
+ _mainPS.println();
+
+ // model constructor
+ _mainPS.printPrefixln("sc_application(sc_module_name name)");
+
+ // parameter of constructor (processes)
+ _mainPS.printPrefixln(": sc_module(name),");
+ pIt = x.getProcessList().iterator();
+ while (pIt.hasNext()) {
+ Process p = pIt.next();
+ _mainPS.printPrefixln(p.getName() + "_ins(\""
+ + p.getName() +"\"),");
+ }
+
+ // parameter of constructor (channels)
+ cIt = _channels.iterator();
+ while (cIt.hasNext()) {
+ Channel c = _map.getPN().getChannel( cIt.next() );
+ _mainPS.printPrefix(c.getName() + "_ins(\""
+ + c.getName() +"\", "
+ + c.getSize()*c.getTokenSize()
+ + ")");
+ if (cIt.hasNext())
+ _mainPS.println(",");
+ else
+ _mainPS.println();
+ }
+ _mainPS.printLeftBracket();
+
+ //construtor content
+ //build the network
+ cIt = _channels.iterator();
+ while (cIt.hasNext())
+ {
+ Channel c = _map.getPN().getChannel(cIt.next());
+ c.accept( new HdsdModulePNVisitor(x, _mainPS) );
+ }
+ _mainPS.println();
+
+ _mainPS.println();
+
+ _mainPS.printPrefixln("SC_THREAD(thread_init);");
+ // init thread
+ _mainPS.printPrefixln("SC_THREAD(thread_sched);");
+
+ // declare concurrent non-terminating threads
+ pIt = x.getProcessList().iterator();
+ while (pIt.hasNext()) {
+ _mainPS.printPrefixln("SC_THREAD(thread_" +
+ pIt.next().getName() + ");");
+ }
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+ //define scheduler thread
+ _mainPS.printPrefixln("void thread_init()");
+ _mainPS.printLeftBracket();
+ //init
+ pIt = x.getProcessList().iterator();
+ while (pIt.hasNext()) {
+ Process p = pIt.next();
+ _mainPS.printPrefixln(p.getName() + "_ins.initialize();");
+ }
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+
+ //different scheduling algorithm can be put here
+ _mainPS.printPrefixln("void thread_sched()");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("while (1)");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("for (iter=eventList.begin(); iter != "
+ + "eventList.end(); ++iter)");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("sc_event* e = (*iter);");
+ _mainPS.printPrefixln("e->notify();");
+ _mainPS.printRightBracket();
+ _mainPS.printPrefixln("eventList.clear();");
+ _mainPS.printPrefixln("wait(sched_event);");
+ _mainPS.printRightBracket();
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+ //define threads
+ pIt = x.getProcessList().iterator();
+ while (pIt.hasNext())
+ pIt.next().accept( new HdsdModulePNVisitor(x, _mainPS) );
+
+ /* begin of profiling: initialization function. */
+ /* - opens file */
+ /* - writes a list of all channels with the connected ports to the file. */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("void initialize_profiler()");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("if ((profiler_output_file = fopen(PROFILER_OUTPUT_FILENAME,\"w\"))==NULL)");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("printf(\"Unable to open profiler output file. No profiling output is written.\\n\");");
+ _mainPS.printPrefixln("return;");
+ _mainPS.printRightBracket();
+ //_mainPS.printPrefixln("printf(\"Profiling data is written to %s.\\n\", PROFILER_OUTPUT_FILENAME);");
+ _mainPS.println();
+
+ cIt = _channels.iterator();
+ while (cIt.hasNext()) {
+ String cName = cIt.next();
+ Channel ch = _map.getPN().getChannel(cName);
+ Iterator<Port> poIt = ch.getPortList().iterator();
+ String outputString = "fprintf(profiler_output_file, \"c " + ch.getName() + " " + ch.getSize();
+ String outputStringAppendix = "";
+ while (poIt.hasNext()) {
+ Port p = poIt.next();
+ Port peerPort = p.getPeerPort();
+ Resource peerResource = p.getPeerResource();
+
+ if (p.isOutPort()) {
+ // channel.out == process.in
+ String portAddr = null;
+ if ( x.hasProcess(peerResource.getName()) )
+ portAddr = "&(" + peerResource.getName()
+ + "_ins.INPORT_" + peerPort.getBasename()
+ + peerPort.getName().replace(
+ peerPort.getBasename(), "").replaceAll(
+ "_([0-9]+)", "[$1]") + ")";
+ else
+ portAddr = "0x00000000";
+ outputString += " i " + peerResource.getName() + " %p";// + p.getPeerPort().getName();
+ outputStringAppendix += "," + portAddr;
+ } else {
+ String portAddr = null;
+ if ( x.hasProcess(peerResource.getName()) )
+ portAddr = "&(" + peerResource.getName()
+ + "_ins.OUTPORT_" + peerPort.getBasename()
+ + peerPort.getName().replace(
+ peerPort.getBasename(), "").replaceAll(
+ "_([0-9]+)", "[$1]") + ")";
+ else
+ portAddr = "0x00000000";
+ outputString += " o " + peerResource.getName() + " %p";// + p.getPeerPort().getName();
+ outputStringAppendix += "," + portAddr;
+ }
+ }
+ outputString += "\\n\"" + outputStringAppendix + ");";
+ _mainPS.printPrefixln(outputString);
+ }
+ _mainPS.printRightBracket();
+ _mainPS.printPrefixln("#endif");
+ _mainPS.println();
+ /* end of profiling */
+
+ _mainPS.printRightBracket(); // end of class
+ _mainPS.println(";");
+
+ //create and run the simulator
+ _mainPS.printPrefixln("int sc_main (int argc, char *argv[])");
+ _mainPS.printLeftBracket();
+
+ //create an instance of the application model
+ //remove potential whitespaces before using the process
+ //network name as a systemc identifier
+ _mainPS.printPrefixln("sc_application my_app_mdl(\""
+ + x.getName().replaceAll(" ", "") + "\");");
+
+ /* begin of profiling: initialize the profiler */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("my_app_mdl.initialize_profiler();");
+ _mainPS.printPrefixln("#endif");
+ _mainPS.printPrefixln();
+ /* end of profiling */
+
+ /* begin distributed simulation */
+ if (UserInterface.getInstance().getDebugFlag())
+ _mainPS.printPrefixln("scd_set_loglevel(SCD_DEBUG);");
+ else
+ _mainPS.printPrefixln("scd_set_loglevel(SCD_INFO);");
+ // simulator && master/slaves
+ Configuration opt = x.getCfg("master");
+ if (opt != null && opt.getValue().equals("true")) // master
+ {
+ // simulator constructor
+ _mainPS.printPrefixln("scd_simulator sim(\""
+ + x.getName() + "\", \""
+ + x.getCfg("address").getValue() + "\", "
+ + x.getCfg("port").getValue() + ", SCD_MASTER);");
+ // register slaves
+ Iterator<Processor> iter = _map.getProcessorList().iterator();
+ while (iter.hasNext())
+ {
+ Processor p = iter.next();
+ opt = p.getCfg("master");
+ if ( !(opt != null && opt.getValue().equals("true")) )
+ {
+ _mainPS.printPrefixln("sim.get_cont_man()."
+ + "register_slave(\"" + p.getName()
+ + "\");");
+ }
+ }
+ } // end master
+ else // slave
+ {
+ // simulator constructor
+ _mainPS.printPrefixln("scd_simulator sim(\""
+ + x.getName() + "\", \""
+ + x.getCfg("address").getValue() + "\", "
+ + x.getCfg("port").getValue() + ", SCD_SLAVE);");
+ // find and set master
+ Iterator<Processor> iter = _map.getProcessorList().iterator();
+ while (iter.hasNext())
+ {
+ Processor p = iter.next();
+ opt = p.getCfg("master");
+ if (opt != null && opt.getValue().equals("true"))
+ {
+ _mainPS.printPrefixln("sim.get_cont_man().set_master(\""
+ + p.getCfg("address").getValue() + "\", "
+ + p.getCfg("port").getValue() + ");");
+ break;
+ }
+ }
+ } // end slave
+
+ // register channels
+ // remote out channels
+ cIt = _remOutChannels.iterator();
+ while (cIt.hasNext())
+ {
+ String cName = cIt.next();
+ Channel c = _map.getPN().getChannel(cName);
+ Iterator<Port> poIt = c.getPortList().iterator();
+ Processor p = null;
+ while (poIt.hasNext())
+ {
+ Port po = poIt.next();
+ if (po.isOutPort())
+ {
+ Process pr = _map.getProcess(
+ po.getPeerResource().getName() );
+ p = pr.getProcessor();
+ }
+ }
+ _mainPS.printPrefixln("sim.get_chan_man()."
+ + "register_channel(\"" + cName + "\",");
+ _mainPS.printPrefixln(" my_app_mdl." + cName
+ + "_ins, \"" + p.getCfg("address").getValue() + "\", "
+ + p.getCfg("port").getValue() + ");");
+ }
+ // remote in channels
+ cIt = _remInChannels.iterator();
+ while (cIt.hasNext())
+ {
+ String cName = cIt.next();
+ _mainPS.printPrefixln("sim.get_chan_man().register_channel("
+ + "\"" + cName + "\",");
+ _mainPS.printPrefixln(" my_app_mdl." + cName + "_ins);");
+ }
+
+ // init & start
+ _mainPS.printPrefixln("bool ret = sim.init();");
+ _mainPS.printPrefixln("if (ret)");
+ _mainPS.prefixInc();
+ _mainPS.printPrefixln("ret = sim.start();");
+ _mainPS.prefixDec();
+ _mainPS.printPrefixln();
+ /* end distributed simulation */
+
+ /* begin of profiling: close the output file */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("if (profiler_output_file != NULL) fclose(profiler_output_file);");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln("if (ret)");
+ _mainPS.prefixInc();
+ _mainPS.printPrefixln("return 0;");
+ _mainPS.prefixDec();
+ _mainPS.printPrefixln("else");
+ _mainPS.prefixInc();
+ _mainPS.printPrefixln("return 1;");
+ _mainPS.prefixDec();
+
+ _mainPS.printRightBracket();
+
+ }
+ catch (Exception e) {
+ System.out.println("HdsdModuleVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Retrieves all channels that have an endpoint on the specified
+ * processor and fills them into the channel sets.
+ * @param x the processor to get the channels for
+ */
+ private void _getChannels(Processor x)
+ {
+ Iterator<Channel> iter = _map.getPN().getChannelList().iterator();
+
+ while (iter.hasNext())
+ {
+ Channel c = iter.next();
+
+ boolean isIn = false;
+ boolean isOut = false;
+
+ /* check if the in/out endpoint of this channel is on this
+ * processor
+ */
+ Iterator<Port> poIt = c.getPortList().iterator();
+ while (poIt.hasNext())
+ {
+ Port p = poIt.next();
+ if (x.hasProcess(p.getPeerResource().getName()))
+ {
+ if (p.isInPort()) // inPort of channel = outport
+ isOut = true;
+ if (p.isOutPort()) // outPort of channel = inport
+ isIn = true;
+ }
+ }
+
+ // add name to channel lists
+ if (isIn && isOut)
+ {
+ _channels.add(c.getName());
+ _locChannels.add(c.getName());
+ }
+ else if (isIn && !isOut)
+ {
+ _channels.add(c.getName());
+ _remInChannels.add(c.getName());
+ }
+ else if (!isIn && isOut)
+ {
+ _channels.add(c.getName());
+ _remOutChannels.add(c.getName());
+ }
+ }
+ } // _getChannels()
+
+
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected Mapping _map = null;
+
+ protected Set<String> _channels = null;
+ protected Set<String> _remInChannels = null;
+ protected Set<String> _remOutChannels = null;
+ protected Set<String> _locChannels = null;
+}
--- /dev/null
+package dol.visitor.hdsd;
+
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.Resource;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * Visitor that generates the main program thread of a process
+ * and the process network in the constructor.
+ */
+public class HdsdModulePNVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public HdsdModulePNVisitor(Processor processor, CodePrintStream stream) {
+ _processor = processor;
+ _mainPS = stream;
+ }
+
+ /**
+ * Generates the thread for this process.
+ *
+ * @param x process that needs to be rendered
+ */
+ public void visitComponent(Process x) {
+ _mainPS.printPrefixln("void thread_" + x.getName() + "()");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("while (!" + x.getName()
+ + "_ins.isDetached())");
+ _mainPS.printLeftBracket();
+
+ /* begin of profiling: start event */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("if (profiler_output_file != NULL) fprintf(profiler_output_file, \"%u "+ x.getName() + " started.\\n\", profiler_event_counter++);");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln(x.getName() + "_ins.fire();");
+
+ /* begin of profiling: stop event */
+ _mainPS.printPrefixln("#ifdef INCLUDE_PROFILER");
+ _mainPS.printPrefixln("if (profiler_output_file != NULL) fprintf(profiler_output_file, \"%u "+ x.getName() + " stopped.\\n\", profiler_event_counter++);");
+ _mainPS.printPrefixln("#endif");
+ /* end of profiling */
+
+ _mainPS.printPrefixln("eventList.push_back(&" + x.getName()
+ + "_event);");
+ _mainPS.printPrefixln("sched_event.notify(SC_ZERO_TIME);");
+ _mainPS.printPrefixln("wait(" + x.getName() + "_event);");
+
+ _mainPS.printRightBracket();
+ _mainPS.printRightBracket();
+ }
+
+ /**
+ * Generates the process network. This is the channel content
+ * in the model constructor.
+ * @param x channel that needs to be rendered
+ */
+ public void visitComponent(Channel x) {
+ for (Port p : x.getPortList()) {
+ Port peerPort = (Port)(p.getPeerPort());
+ Resource peerResource = p.getPeerResource();
+
+ if (!_processor.hasProcess(peerResource.getName()))
+ continue;
+
+ if (peerPort.getRange() != null) {
+ if (p.isOutPort()) {
+ _mainPS.printPrefixln(peerResource.getName()
+ + "_ins.INPORT_"
+ + peerPort.getBasename()
+ + peerPort.getName().replace(
+ peerPort.getBasename(), "").replaceAll(
+ "_([0-9]+)", "[$1]") + "(" + x.getName()
+ + "_ins);");
+ }
+ else if (p.isInPort()) {
+ _mainPS.printPrefixln(peerResource.getName()
+ + "_ins.OUTPORT_"
+ + peerPort.getBasename()
+ + peerPort.getName().replace(
+ peerPort.getBasename(), "").replaceAll(
+ "_([0-9]+)", "[$1]") + "(" + x.getName()
+ + "_ins);");
+ }
+ }
+ else {
+ if (p.isOutPort()) {
+ _mainPS.printPrefixln(peerResource.getName()
+ + "_ins.INPORT_" + peerPort.getName()
+ + "(" + x.getName() + "_ins);");
+ }
+ else if (p.isInPort()) {
+ _mainPS.printPrefixln(peerResource.getName()
+ + "_ins.OUTPORT_" + peerPort.getName()
+ + "(" + x.getName() + "_ins);");
+ }
+ }
+ }
+ }
+
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected Mapping _map = null;
+ protected Processor _processor = null;
+}
--- /dev/null
+package dol.visitor.hdsd;
+
+import java.util.Iterator;
+
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.visitor.MapVisitor;
+
+/**
+ * Visitor that generates the main programs of distributed simulators.
+ */
+public class HdsdModuleVisitor extends MapVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of this file
+ */
+ public HdsdModuleVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ * @param x mapping that needs to be rendered
+ */
+ public void visitComponent(Mapping x) {
+ Iterator<Processor> iter;
+ iter = x.getProcessorList().iterator();
+ while (iter.hasNext())
+ {
+ Processor p = iter.next();
+ p.accept(new HdsdModuleArchVisitor(x, _dir));
+ }
+ }
+
+ protected String _dir = null;
+}
--- /dev/null
+package dol.visitor.hdsd;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.SourceCode;
+import dol.util.CodePrintStream;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ * Visitor that is used to generate
+ * a wrapper class for a process: process_wrapper.[h/cpp].
+ */
+public class HdsdProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir target directory
+ */
+ public HdsdProcessVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ Vector<String> pList = new Vector<String>();
+
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ pList.add(basename);
+ p.accept(this);
+ }
+ }
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param p process that needs to be rendered
+ */
+ public void visitComponent(Process p) {
+ try {
+ _createCppFile(p);
+ _createHeaderFile(p);
+ _adaptSources(p);
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _adaptSources(Process p) throws IOException {
+ Sed sed = new Sed();
+ for (Port port : p.getPortList()) {
+ String processHeaderFile;
+
+ for (SourceCode sr : p.getSrcList()) {
+ processHeaderFile = _dir + _delimiter + ".."
+ + _delimiter + "processes" + _delimiter
+ + sr.getLocality().
+ replaceAll("(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ if (port.isOutPort()) {
+ sed.sed(processHeaderFile,
+ "(#define[ ]*PORT_\\w*[ ]*)\"?"
+ + port.getBasename() + "\"?",
+ "$1 " + "&((static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))->OUTPORT_"
+ + port.getBasename() + ")");
+
+ }
+ else if (port.isInPort()) {
+ sed.sed(processHeaderFile,
+ "(#define[ ]*PORT_\\w*[ ]*)\"?"
+ + port.getBasename() + "\"?",
+ "$1 " + "&((static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))->INPORT_"
+ + port.getBasename() + ")");
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _createCppFile(Process p) throws IOException {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ ps.printPrefixln("#include \"" + p.getBasename()
+ + "_wrapper.h\"");
+ ps.printPrefixln();
+
+ //define the write/read
+ if (p.hasOutPorts()) {
+ ps.printPrefixln("static inline int DOL_write(void *port, "
+ + "void *buf, int len, DOLProcess *process)");
+ ps.printLeftBracket();
+ ps.printPrefixln("sc_port<write_if> *write_port = static_cast"
+ + "<sc_port<write_if> *>(port);");
+ ps.printPrefixln("char *str = static_cast<char*>(buf);");
+
+ /* begin of profiling: write event */
+ ps.printPrefixln("#ifdef INCLUDE_PROFILER");
+ ps.printPrefixln("(static_cast<" + p.getBasename()
+ + "_wrapper *>(process->wptr))" + "->addToProfile(\"w\", port, len);");
+ ps.printPrefixln("#endif");
+ /* end of profiling */
+
+ ps.printPrefixln("while (len-- > 0) ");
+ ps.printPrefixln(" (*write_port)->write(*str++);");
+ ps.printRightBracket();
+ ps.printPrefixln();
+ ps.printPrefixln("static inline int DOL_wtest(void *port, "
+ + "int len, DOLProcess *process)");
+ ps.printLeftBracket();
+ ps.printPrefixln("sc_port<write_if> *write_port = static_cast"
+ + "<sc_port<write_if> *>(port);");
+ ps.printPrefixln("return (*write_port)->wtest(len);");
+ ps.printRightBracket();
+ ps.printPrefixln();
+ }
+ if (p.hasInPorts()) {
+ ps.printPrefixln("static inline int DOL_read(void *port, "
+ + "void *buf, int len, DOLProcess *process)");
+ ps.printLeftBracket();
+ ps.printPrefixln("sc_port<read_if> *read_port = static_cast"
+ + "<sc_port<read_if> *>(port);");
+ ps.printPrefixln("char *str = static_cast<char*>(buf);");
+
+ /* begin of profiling: read event */
+ ps.printPrefixln("#ifdef INCLUDE_PROFILER");
+ ps.printPrefixln("(static_cast<" + p.getBasename()
+ + "_wrapper *>(process->wptr))" + "->addToProfile(\"r\", port, len);");
+ ps.printPrefixln("#endif");
+ /* end of profiling */
+
+ ps.printPrefixln("while (len-- > 0) ");
+ ps.printPrefixln(" (*read_port)->read(*str++);");
+ ps.printRightBracket();
+ ps.printPrefixln();
+ ps.printPrefixln("static inline int DOL_rtest(void *port, "
+ + "int len, DOLProcess *process)");
+ ps.printLeftBracket();
+ ps.printPrefixln("sc_port<read_if> *read_port = static_cast"
+ + "<sc_port<read_if> *>(port);");
+ ps.printPrefixln("return (*read_port)->rtest(len);");
+ ps.printRightBracket();
+ }
+ ps.printPrefixln();
+ ps.printPrefixln("static inline int DOL_detach(DOLProcess *p)");
+ ps.printLeftBracket();
+ ps.printPrefixln("(static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))" + "->setDetached();");
+ ps.printRightBracket();
+ ps.printPrefixln();
+
+ ps.printPrefixln("#define GETINDEX(dimension) \\");
+ ps.printPrefixln("(static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))->_processIndex[dimension]");
+ ps.printPrefixln();
+ //include c file
+ for (SourceCode sr : p.getSrcList()) {
+ ps.printPrefixln("#include \"" + sr.getLocality() + "\"");
+ }
+ ps.printPrefixln();
+
+ /* begin of profiling: function that adds an entry to the profile */
+ ps.printPrefixln("#ifdef INCLUDE_PROFILER");
+ ps.printPrefixln("void " + p.getBasename() + "_wrapper::addToProfile(const char *evnt, void *port, int length)");
+ ps.printLeftBracket();
+ ps.printPrefixln("if (profiler_output_file != NULL) fprintf(profiler_output_file, \"%u %s %s %p %d\\n\", profiler_event_counter++, _uniqueName, evnt, port, length);");
+ ps.printRightBracket();
+ ps.printPrefixln("#endif");
+ /* end of profiling */
+
+ ps.printPrefixln("void " + p.getBasename()
+ + "_wrapper::setDetached() { _detached = 1; }");
+ ps.printPrefixln("int " + p.getBasename()
+ + "_wrapper::isDetached() { return _detached; }");
+ ps.printPrefixln();
+
+ //constructor
+ ps.printPrefixln(p.getBasename() + "_wrapper::" + p.getBasename()
+ + "_wrapper(sc_module_name name=sc_gen_unique_name(\""
+ + p.getBasename() + "\" )) : sc_module(name), _process("
+ + p.getBasename() + ")" + ", _detached(0)");
+ ps.printLeftBracket();
+ ps.printPrefixln("struct _local_states *_state = "
+ + "new struct _local_states;");
+ ps.printPrefixln("memcpy(_state, " + p.getBasename()
+ + ".local, sizeof(struct _local_states));");
+ ps.printPrefixln("_process.local = _state;");
+ //ps.printPrefixln("sprintf(_process.local->id, name);");
+ ps.printPrefixln("_process.wptr = this;");
+ ps.printPrefixln();
+ ps.printPrefixln("char buffer[255];");
+ ps.printPrefixln("sprintf(buffer, name);");
+
+ /* begin of profiling: save unique name for writing it to
+ the profile later */
+ ps.printPrefixln("#ifdef INCLUDE_PROFILER");
+ ps.printPrefixln("sprintf(_uniqueName, name);");
+ ps.printPrefixln("#endif");
+ /* end of profiling */
+
+ ps.printPrefixln("for (int i = 0; i < 4; i++)");
+ ps.printPrefixln(" _processIndex[i] = "
+ + "getIndex(buffer, \"_\", i);");
+
+ ps.printPrefixln();
+ ps.printRightBracket();
+
+ ps.printPrefixln();
+ ps.printPrefixln("void " + p.getBasename()
+ + "_wrapper::initialize()");
+ ps.printLeftBracket();
+ ps.printPrefixln("_process.init(&_process);");
+ ps.printRightBracket();
+ ps.printPrefixln();
+ ps.printPrefixln("int " + p.getBasename() + "_wrapper::fire()");
+ ps.printLeftBracket();
+ ps.printPrefixln();
+ ps.printPrefixln("return _process.fire(&_process);");
+ ps.printRightBracket();
+ }
+
+ protected void _createHeaderFile(Process p)
+ throws IOException {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.h";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ ps.printPrefixln("#ifndef " + p.getBasename() + "_WRAPPER_H");
+ ps.printPrefixln("#define " + p.getBasename() + "_WRAPPER_H");
+ ps.printPrefixln();
+ ps.printPrefixln("#include \"systemc.h\"");
+ ps.printPrefixln();
+ ps.printPrefixln("#include \"dol_sched_if.h\"");
+ ps.printPrefixln("#include \"simple_fifo.h\"");
+ ps.printPrefixln();
+ ps.printPrefixln("#include <dol.h>");
+ ps.printPrefixln();
+
+ /* begin of profiling: externally defined global variables */
+ ps.println();
+ ps.printPrefixln("#ifdef INCLUDE_PROFILER");
+ ps.printPrefixln("extern FILE *profiler_output_file;");
+ ps.printPrefixln("extern unsigned int profiler_event_counter;");
+ ps.printPrefixln("#endif");
+ ps.printPrefixln();
+ /* end of profiling */
+
+ ps.printPrefixln("class " + p.getBasename() +
+ "_wrapper : virtual public dol_sched_if, " +
+ "public sc_module");
+ ps.printLeftBracket();
+ ps.printPrefixln("public:");
+
+
+ Vector<String> portList = new Vector<String>();
+ for (Port port : p.getPortList()) {
+ String basename = port.getBasename();
+
+ if (!portList.contains(basename)) {
+ portList.add(basename);
+
+ if (!port.getRange().equals("")) {
+ if (port.isOutPort()) {
+ ps.printPrefixln("sc_port<write_if> OUTPORT_"
+ + port.getBasename() + "["
+ + port.getRange().replaceAll(
+ ";", "\\]\\[") + "];");
+ }
+ else if (port.isInPort()) {
+ ps.printPrefixln("sc_port<read_if> INPORT_"
+ + port.getBasename() + "["
+ + port.getRange().replaceAll(
+ ";", "\\]\\[") + "];");
+ }
+ }
+ else {
+ if (port.isOutPort()) {
+ ps.printPrefixln("sc_port<write_if> OUTPORT_"
+ + port.getName() + ";");
+ }
+ else if (port.isInPort()) {
+ ps.printPrefixln("sc_port<read_if> INPORT_"
+ + port.getName() + ";");
+ }
+ }
+ }
+ }
+ ps.printPrefixln("int _processIndex[4];");
+
+ /* begin of profiling: name variable declaration */
+ ps.printPrefixln("#ifdef INCLUDE_PROFILER");
+ ps.printPrefixln("char _uniqueName[255];");
+ ps.printPrefixln("#endif");
+ /* end of profiling */
+
+ ps.printPrefixln();
+ ps.printPrefixln("" + p.getBasename()
+ + "_wrapper(sc_module_name name);");
+ ps.printPrefixln();
+ ps.printPrefixln("~" + p.getBasename() + "_wrapper() {}");
+ ps.printPrefixln();
+
+ /* begin of profiling: addtoprofile member function */
+ ps.printPrefixln("#ifdef INCLUDE_PROFILER");
+ ps.printPrefixln("void addToProfile(const char *, void *, int);");
+ ps.printPrefixln("#endif");
+ ps.printPrefixln();
+ /* end of profiling */
+
+ ps.printPrefixln("// DOL scheduler interface");
+ ps.printPrefixln("void initialize();");
+ ps.printPrefixln("int fire();");
+ ps.printPrefixln("void setDetached();");
+ ps.printPrefixln("int isDetached();");
+ ps.printPrefixln();
+ ps.printPrefixln();
+ ps.printPrefixln("protected:");
+ ps.printPrefixln();
+ ps.printPrefixln("private:");
+ ps.printPrefixln("" + p.getBasename() + "_wrapper( const "
+ + p.getBasename() + "_wrapper& );");
+ ps.printPrefixln("" + p.getBasename() + "_wrapper& operator = "
+ + "( const " + p.getBasename() + "_wrapper& );");
+ ps.printPrefixln("DOLProcess _process;");
+ ps.printPrefixln("int _detached;");
+ ps.printRightBracket();
+ ps.printPrefixln(";");
+ ps.printPrefixln("#endif");
+ }
+
+ protected String _dir = null;
+}
--- /dev/null
+package dol.visitor.hdsd;
+
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.List;
+
+import dol.datamodel.architecture.Configuration;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.main.UserInterface;
+import dol.util.CodePrintStream;
+import dol.visitor.MapVisitor;
+
+/**
+ * Visitor that is used to generate a shell script to
+ * distribute, run, monitor, profile and clean up a distributed
+ * simulation.
+ */
+public class HdsdScriptVisitor extends MapVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of the shell script
+ */
+ public HdsdScriptVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ * Create the shell script for the given mapping.
+ *
+ * @param x mapping that needs to be rendered.
+ */
+ public void visitComponent(Mapping x) {
+ try {
+ String filename = _dir + "/" + "scd.sh";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ List<Processor> pList = x.getProcessorList();
+ int numProcessors = pList.size();
+
+ // arrays to hold strings for generation
+ String[] hNames = new String[numProcessors];
+ String[] hAddrs = new String[numProcessors];
+ String[] hDirs = new String[numProcessors];
+ String[] hUsers = new String[numProcessors];
+
+ // get processor information and fill to string arrays
+ int numSlaves = 0;
+ Iterator<Processor> iter = pList.iterator();
+ while (iter.hasNext())
+ {
+ Processor p = iter.next();
+ int pIdx = numSlaves;
+ boolean master = false;
+ Configuration c = p.getCfg("master");
+ if (c != null && c.getValue().equals("true"))
+ master = true;
+
+ // if it is the master, it will be the last processor
+ if (master)
+ pIdx = numProcessors-1;
+
+ // fill information to string arrays
+ hNames[pIdx] = p.getName();
+ hAddrs[pIdx] = p.getCfg("address").getValue();
+ c = p.getCfg("basedir");
+ if (c != null)
+ {
+ String dir = c.getValue();
+ // remove tailing '/'
+ if ( dir.endsWith("/") )
+ dir = dir.replaceAll("/" + "$", "");
+ if (dir.equals(""))
+ hDirs[pIdx] = hNames[pIdx];
+ else
+ hDirs[pIdx] = dir + "/" + hNames[pIdx];
+ }
+ else
+ hDirs[pIdx] = hNames[pIdx];
+ c = p.getCfg("username");
+ if (c != null)
+ hUsers[pIdx] = c.getValue() + "@";
+ else
+ hUsers[pIdx] = "";
+
+ if (!master)
+ numSlaves++;
+ } // end get and fill information
+
+ /* generate script */
+ // head
+ ps.println("#!/bin/bash");
+ ps.println();
+ ps.println("SCRIPTNAME=\"`echo $0 | sed 's/.*\\///'`\"");
+ ps.println();
+
+ // host configuration
+ ps.println("### host configuration");
+ ps.print("NAME=( ");
+ for (int i=0; i<numProcessors; i++)
+ ps.print("\"" + hNames[i] + "\" ");
+ ps.println(")");
+ ps.print("ADDR=( ");
+ for (int i=0; i<numProcessors; i++)
+ ps.print("\"" + hAddrs[i] + "\" ");
+ ps.println(")");
+ ps.print("DIR=( ");
+ for (int i=0; i<numProcessors; i++)
+ ps.print("\"" + hDirs[i] + "\" ");
+ ps.println(")");
+ ps.print("USER=( ");
+ for (int i=0; i<numProcessors; i++)
+ ps.print("\"" + hUsers[i] + "\" ");
+ ps.println(")");
+ ps.println();
+
+ // paths
+ ps.println("### dol classpath");
+ ps.println("DOLPATH=\"" + _ui.getDOLPath() + "\"");
+ ps.println("CLASSPATH=\"${DOLPATH}/jars/jdom.jar:"
+ + "${DOLPATH}/jars/xercesImpl.jar:"
+ + "${DOLPATH}/build/bin/main\"");
+ ps.println("export CLASSPATH");
+ ps.println();
+ ps.println("### systemcd path");
+ ps.println("SCDPATH=\"" + System.getProperty("user.dir")
+ + "/" + _dir + "\"");
+ ps.println();
+
+ // function usage
+ ps.println("### function declarations");
+ ps.println();
+ ps.println("# function: prints usage information");
+ ps.println("function usage()");
+ ps.println("{");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Usage: ${SCRIPTNAME} COMMAND [OPTION]\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo -e \"distribute\\tdistributes the binaries to the simulators\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo -e \"run\\t\\truns the simulation and prints stdout of the master\"");
+ ps.printPrefixln("echo -e \"\\t\\tall stdouts are written to stdout_NETSIM.txt\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo -e \"check\\t\\tchecks which simulators are still active\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo -e \"kill\\t\\tkills all simulators\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo -e \"profile PN.xml\\tretrieves the profiles from the simulators,\" \\");
+ ps.prefixInc();
+ ps.printPrefixln("\"processes them and\"");
+ ps.prefixDec();
+ ps.printPrefixln("echo -e \"\\t\\tstores the cumulative results in PN_annotaded.xml\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo -e \"cleanup\\t\\tremoves the simulation directory on all simulators\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo -e \"help, -h\\tprints this help\"");
+ ps.printPrefixln("echo");
+ ps.prefixDec();
+ ps.println("}");
+ ps.println();
+
+ // function profile
+ ps.println("# function: adds profiling information of one simulator to xml");
+ ps.println("function profile()");
+ ps.println("{");
+ ps.prefixInc();
+ ps.printPrefixln("echo \"Retrieving profile from ${ADDR[$1]}\"");
+ ps.printPrefixln("scp ${USER[$1]}${ADDR[$1]}:${DIR[$1]}/profile_${NAME[$1]}.txt .");
+ ps.printPrefixln("if [ $? -ne 0 ]; then");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Retrieving profile from ${NAME[$1]} failed!\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("rm scd_tmp_profiled.xml");
+ ps.printPrefixln("exit 1");
+ ps.prefixDec();
+ ps.printPrefixln("fi");
+ ps.printPrefixln("echo \"Profiling ${NAME[$1]}\"");
+ ps.printPrefixln("java dol.main.Main -P scd_tmp_profiled.xml -T profile_${NAME[$1]}.txt > scd_profilerout.txt 2>&1");
+ ps.printPrefixln("if [ $? -ne 0 ]; then");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Profiling ${NAME[$1]} failed!\"");
+ ps.printPrefixln("echo \"Check scd_tmp_profilerout.txt for more information.\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("rm scd_tmp_profiled.xml");
+ ps.printPrefixln("exit 1");
+ ps.prefixDec();
+ ps.printPrefixln("fi");
+ ps.printPrefixln("rm scd_profilerout.txt");
+ ps.printPrefixln("mv scd_tmp_profiled_annotated.xml scd_tmp_profiled.xml");
+ ps.printPrefixln("rm profile_${NAME[$1]}.txt");
+ ps.prefixDec();
+ ps.println("}");
+ ps.println();
+
+ // main programm start
+ ps.println("### main program");
+ ps.println();
+ ps.println("# require at least one argument");
+ ps.println("if [ ! $# -ge 1 ]; then");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Error: At least one argument is required!\"");
+ ps.printPrefixln("usage");
+ ps.printPrefixln("exit 1");
+ ps.prefixDec();
+ ps.println("fi");
+ ps.println();
+ ps.println("# switch on operation");
+ ps.println("case \"$1\" in");
+
+ // distribute binaries to simulators
+ ps.println("\"distribute\")");
+ ps.prefixInc();
+ ps.printPrefixln("echo \"Distributing binaries to simulators...\"");
+ ps.printPrefixln("# prepare directories");
+ for (int i=0; i<numProcessors; i++)
+ ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
+ + "]} \"test -d ${DIR[" + i + "]} || mkdir -p "
+ + "${DIR[" + i + "]}\"");
+ ps.printPrefixln("# copy files");
+ for (int i=0; i<numProcessors; i++)
+ ps.printPrefixln("scp ${SCDPATH}/scd_${NAME[" + i
+ + "]} ${USER[" + i + "]}${ADDR[" + i
+ + "]}:${DIR[" + i + "]}/");
+ ps.prefixDec();
+ ps.println(";;");
+
+ // run the simulation
+ ps.println("\"run\")");
+ ps.prefixInc();
+ ps.printPrefixln("echo \"Running simulation...\"");
+ for (int i=0; i<numProcessors-1; i++)
+ ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
+ + "]} \"cd ${DIR[" + i + "]}; ./scd_${NAME["
+ + i + "]}\" > stdout_${NAME[" + i + "]}.txt 2>&1 &");
+ ps.printPrefixln("ssh ${USER[" + (numProcessors-1)
+ + "]}${ADDR[" + (numProcessors-1)
+ + "]} \"cd ${DIR[" + (numProcessors-1)
+ + "]}; ./scd_${NAME[" + (numProcessors-1)
+ + "]}\" 2>&1 | tee stdout_${NAME["
+ + (numProcessors-1) + "]}.txt");
+ ps.prefixDec();
+ ps.println(";;");
+
+ // check if simulators are running
+ ps.println("\"check\")");
+ ps.prefixInc();
+ ps.printPrefixln("echo \"Checking which simulators are active...\"");
+ for (int i=0; i<numProcessors; i++)
+ ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i + "]} \"pgrep -x scd_${NAME[" + i + "]} > /dev/null && echo ${NAME[" + i + "]} is active || echo ${NAME[" + i + "]} is not active\"");
+ ps.prefixDec();
+ ps.println(";;");
+
+ // kill all simulators
+ ps.println("\"kill\")");
+ ps.prefixInc();
+ ps.printPrefixln("echo \"Killing all simulators...\"");
+ for (int i=0; i<numProcessors; i++)
+ ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i + "]} \"killall -e scd_${NAME[" + i + "]}\"");
+ ps.prefixDec();
+ ps.println(";;");
+
+ // get and process profiles
+ ps.println("\"profile\")");
+ ps.prefixInc();
+ ps.printPrefixln("# require 2 arguments");
+ ps.printPrefixln("if [ $# -ne 2 ]; then");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Error: Illegal number of arguments!\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Usage: ${SCRIPTNAME} profile processnetwork.xml\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("exit 1");
+ ps.prefixDec();
+ ps.printPrefixln("fi");
+ ps.println();
+ ps.printPrefixln("# check if process nework file exists");
+ ps.printPrefixln("if [ ! -f \"$2\" ]; then");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Error: File not found!\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("exit 1");
+ ps.prefixDec();
+ ps.printPrefixln("fi");
+ ps.println();
+ ps.printPrefixln("# check file extension");
+ ps.printPrefixln("echo $2 | grep -e '\\.xml$' > /dev/null");
+ ps.printPrefixln("if [ $? -ne 0 ]; then");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Error: Illegal file extension: required .xml!\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("exit 1");
+ ps.prefixDec();
+ ps.printPrefixln("fi");
+ ps.println();
+ ps.printPrefixln("PFILE=`echo $2 | sed 's/.*\\///' | sed 's/\\.xml$/_annotated.xml/'`");
+ ps.printPrefixln("echo \"Profiling into ${PFILE}...\"");
+ ps.println();
+ ps.printPrefixln("# check that the DOL is found and the classpath set correctly");
+ ps.printPrefixln("java dol.main.Main > /dev/null 2>&1");
+ ps.printPrefixln("if [ $? -eq 1 ]; then");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"DOL framework not found!\"");
+ ps.printPrefixln("echo");
+ ps.printPrefixln("exit 1");
+ ps.prefixDec();
+ ps.printPrefixln("fi");
+ ps.printPrefixln("cp \"$2\" scd_tmp_profiled.xml");
+ ps.println();
+ for (int i=0; i<numProcessors; i++)
+ ps.printPrefixln("profile " + i);
+ ps.println();
+ ps.printPrefixln("mv scd_tmp_profiled.xml \"${PFILE}\"");
+ ps.prefixDec();
+ ps.println(";;");
+
+ // deleting remote files
+ ps.printPrefixln("\"cleanup\")");
+ ps.prefixInc();
+ ps.printPrefixln("echo \"Deleting simulator directory on simulators...\"");
+ for (int i=0; i<numProcessors; i++)
+ ps.printPrefixln("ssh ${USER[" + i + "]}${ADDR[" + i
+ + "]} \"rm -r ${DIR[" + i + "]}\"");
+ ps.prefixDec();
+ ps.println(";;");
+
+ // tail
+ ps.println("\"help\")");
+ ps.prefixInc();
+ ps.printPrefixln("usage");
+ ps.prefixDec();
+ ps.println(";;");
+ ps.println("\"-h\")");
+ ps.prefixInc();
+ ps.printPrefixln("usage");
+ ps.prefixDec();
+ ps.println(";;");
+ ps.println("\"--help\")");
+ ps.prefixInc();
+ ps.printPrefixln("usage");
+ ps.prefixDec();
+ ps.println(";;");
+ ps.println("*)");
+ ps.prefixInc();
+ ps.printPrefixln("echo");
+ ps.printPrefixln("echo \"Error: Illegal command: $1\"");
+ ps.printPrefixln("usage");
+ ps.printPrefixln("exit 1");
+ ps.prefixDec();
+ ps.println(";;");
+ ps.println("esac");
+
+ } catch (Exception e) {
+ System.out.println("HdsdMakefileVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+
+ } // end visitor
+
+ protected String _dir = null;
+ protected UserInterface _ui = UserInterface.getInstance();
+}
+
--- /dev/null
+package dol.visitor.hdsd;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import dol.datamodel.mapping.Mapping;
+import dol.util.CodePrintStream;
+import dol.util.Copier;
+import dol.visitor.MapVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a HdS package with distributed simulation support.
+ */
+public class HdsdVisitor extends MapVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param packageName name of the HdSd directory
+ */
+ public HdsdVisitor(String packageName) {
+ _packageName = packageName;
+ }
+
+ /**
+ *
+ * @param x mapping that needs to be rendered.
+ */
+ public void visitComponent(Mapping x) {
+ try {
+ _generateDirHierarchy();
+
+ x.accept(new HdsdMakefileVisitor(_srcDir));
+ x.accept(new HdsdModuleVisitor(_srcDir));
+ x.getPN().accept(new HdsdProcessVisitor(_wrapperDir));
+ x.accept(new HdsdScriptVisitor(_srcDir));
+ }
+ catch (Exception e) {
+ System.out.println("HdSdVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _generateDirHierarchy()
+ throws IOException, FileNotFoundException {
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ _srcDir = _packageName + "/" + _srcDirName;
+ dir = new File(_srcDir);
+ dir.mkdirs();
+
+ _libDir = _srcDir + "/" + _libDirName;
+ dir = new File(_libDir);
+ dir.mkdirs();
+
+ _scdDir = _srcDir + "/" + _scdDirName;
+ dir = new File(_scdDir);
+ dir.mkdirs();
+
+ _processDir = _srcDir + "/" + _processDirName;
+ dir = new File(_processDir);
+ dir.mkdirs();
+
+ _wrapperDir = _srcDir + "/" + _wrapperDirName;
+ dir = new File(_wrapperDir);
+ dir.mkdirs();
+
+ //copy library files
+ String sdir = _ui.getVisitorDir() + "hdsd" + "/" + "lib";
+ File source = new File(sdir);
+ File destination = new File(_libDir);
+ new Copier().copy(source, destination);
+
+ // copy scd library files
+ sdir = _ui.getVisitorDir() + "hdsd" + "/" + "scd";
+ source = new File(sdir);
+ destination = new File(_scdDir);
+ new Copier().copy(source, destination);
+
+ //copy process source code
+ source = new File(_srcDirName);
+ destination = new File(_processDir);
+ new Copier().copy(source, destination);
+ }
+
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+
+ protected String _libDir = "";
+ protected static String _libDirName = "lib";
+
+ protected String _scdDir = "";
+ protected static String _scdDirName = "scd";
+
+ protected String _processDir = "";
+ protected static String _processDirName = "processes";
+
+ protected String _wrapperDir = "";
+ protected static String _wrapperDirName = "sc_wrappers";
+
+ protected String _threadPostfix = "_thread";
+
+ protected CodePrintStream _mainPS = null;
+}
--- /dev/null
+#include "dol.h"
+
+/**
+ * Gets an index of a string, where the index must be separated by
+ * a character specified in tokens.
+ * Returns -1, when an error occurs.
+ *
+ * Example:
+ * getIndex("name_1_2", "_", 0) will return 1.
+ * getIndex("name_1_2", "_", 1) will return 2.
+ *
+ * @param string string to parse
+ * @param tokens delimiter of indices
+ * @param indexNumber position of index (starting at 0)
+ */
+int getIndex(const char* string, char* tokens, int indexNumber) {
+ char* string_copy;
+ char* token_pointer;
+ int index = 0;
+
+ string_copy = (char*) malloc(sizeof(char) * (strlen(string) + 1));
+ if (!string_copy) {
+ fprintf(stderr, "getIndex(): could not allocate memory.\n");
+ return -1;
+ }
+
+ strcpy(string_copy, string);
+
+ token_pointer = strtok(string_copy, tokens);
+ do {
+ token_pointer = strtok(NULL, tokens);
+ index++;
+ } while (index <= indexNumber && token_pointer != 0);
+
+ if (token_pointer) {
+ index = atoi(token_pointer);
+ free(string_copy);
+ return index;
+ }
+
+ return -1;
+}
--- /dev/null
+#ifndef DOL_H
+#define DOL_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __DOL_ETHZ_GEN__
+#include <systemc>
+using sc_core::sc_port;
+#endif
+
+/************************************************************************
+ * do not add code to this header
+ ************************************************************************/
+
+/**
+ * Define the DOL process handler scheme.
+ * - Local variables are defined in structure LocalState. Local
+ * variables may vary from different processes.
+ * - The ProcessInit function pointer points to a function which
+ * initializes a process.
+ * - The ProcessFire function pointer points to a function which
+ * performs the actual computation. The communication between
+ * processes is inside the ProcessFire function.
+ * - The WPTR is a placeholder for callback. One can just
+ * leave it blank.
+ */
+
+//structure for local memory of process
+typedef struct _local_states *LocalState;
+
+//additional behavioral functions could be declared here
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+//process handler
+struct _process;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr; //placeholder for wrapper instance
+} DOLProcess;
+
+
+//macros to deal with iterated ports
+/**
+ ******************************************************
+ * The HdS code is needed to replace the current ETHZ *
+ * implementation. *
+ ******************************************************
+ *
+ * Macro to create a variable to store a port name.
+ *
+ * @param name name of the variable
+ */
+#ifdef __DOL_ETHZ_GEN__
+#define CREATEPORTVAR(name) sc_port<sc_interface> *name
+#else
+#define CREATEPORTVAR(name) // Hds Code
+#endif
+
+/**
+ * Create the port name of an iterated port based on its basename and the
+ * given indices.
+ *
+ * @param port buffer where the result is stored (created using
+ * CREATEPORTVAR)
+ * @param base basename of the port
+ * @param number_of_indices number of dimensions of the port
+ * @param index_range_pairs index and range values for each dimension
+ */
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \
+ createPort(&port, base, number_of_indices, index_range_pairs)
+
+int getIndex(const char* string, char* tokens, int indexNumber);
+
+/*
+ ******************************************************
+ * The HdS code is needed to replace the current ETHZ *
+ * implementation. *
+ ******************************************************
+ */
+#ifdef __DOL_ETHZ_GEN__
+template <class interface>
+sc_port<interface> *createPort(sc_port<interface> **port,
+ void *base,
+ int number_of_indices,
+ int index0, int range0) {
+ *port = &((static_cast<sc_port<interface> *>(base))[index0]);
+ return &((static_cast<sc_port<interface> *>(base))[index0]);
+}
+
+template <class interface>
+sc_port<interface> *createPort(sc_port<interface> **port,
+ void *base,
+ int number_of_indices,
+ int index0, int range0,
+ int index1, int range1) {
+ *port = &((static_cast<sc_port<interface> *>(base))[
+ index0 * range1 + index1]);
+ return &((static_cast<sc_port<interface> *>(base))[
+ index0 * range1 + index1]);
+}
+
+template <class interface>
+sc_port<interface> *createPort(sc_port<interface> **port,
+ void *base,
+ int number_of_indices,
+ int index0, int range0,
+ int index1, int range1,
+ int index2, int range2) {
+ *port = &((static_cast<sc_port<interface> *>(base))[
+ index0 * range1 * range2 + index1 * range0 + index2]);
+ return &((static_cast<sc_port<interface> *>(base))[
+ index0 * range1 * range2 + index1 * range0 + index2]);
+}
+
+template <class interface>
+sc_port<interface> *createPort(sc_port<interface> **port,
+ void *base,
+ int number_of_indices,
+ int index0, int range0,
+ int index1, int range1,
+ int index2, int range2,
+ int index3, int range3) {
+ *port = &((static_cast<sc_port<interface> *>(base))[
+ index0 * range1 * range2 * range3
+ + index1 * range2 * range3 + index2 * range3 + index3]);
+ return &((static_cast<sc_port<interface> *>(base))[
+ index0 * range1 * range2 * range3
+ + index1 * range2 * range3 + index2 * range3 + index3]);
+}
+#else
+#define createPort() //HdS code
+#endif
+
+#endif
--- /dev/null
+/**************************************************************************\r
+ dol_sched_if.h\r
+ \r
+ Scheduler interface for a DOL process \r
+\r
+ (c) 2006 by Alexander Maxiaguine <maxiagui@tik.ee.ethz.ch>\r
+\r
+ Computer Engineering and Networks Laboratory, TIK\r
+ Swiss Federal Institute of Technology, ETHZ Zurich \r
+ Switzerland\r
+\r
+**************************************************************************/\r
+\r
+/**************************************************************************\r
+ Change Log:\r
+\r
+ 14.03.06 -- creation\r
+\r
+**************************************************************************/\r
+\r
+#ifndef DOL_SCHED_IF_H\r
+#define DOL_SCHED_IF_H\r
+\r
+class dol_sched_if \r
+{\r
+\r
+public:\r
+ virtual void initialize() = 0;\r
+ virtual int fire() = 0;\r
+\r
+\r
+protected:\r
+ dol_sched_if() {}\r
+\r
+\r
+private:\r
+\r
+ // disabled\r
+ dol_sched_if( const dol_sched_if& );\r
+ dol_sched_if& operator = ( const dol_sched_if& );\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*****************************************************************************
+
+ The following code is derived, directly or indirectly, from the SystemC
+ source code Copyright (c) 1996-2004 by all Contributors.
+ All Rights reserved.
+
+ The contents of this file are subject to the restrictions and limitations
+ set forth in the SystemC Open Source License Version 2.4 (the "License");
+ You may not use this file except in compliance with such restrictions and
+ limitations. You may obtain instructions on how to receive a copy of the
+ License at http://www.systemc.org/. Software distributed by Contributors
+ under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+ ANY KIND, either express or implied. See the License for the specific
+ language governing rights and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ simple_fifo.cpp -- Simple SystemC 2.0 producer/consumer example.
+
+ From "An Introduction to System Level Modeling in
+ SystemC 2.0". By Stuart Swan, Cadence Design Systems.
+ Available at www.systemc.org
+
+ Original Author: Stuart Swan, Cadence Design Systems, 2001-06-18
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+#ifndef _SIMPLE_FIFO_H_
+#define _SIMPLE_FIFO_H_
+
+#include <systemc>
+using sc_core::sc_interface;
+using sc_core::sc_channel;
+using sc_core::sc_event;
+using sc_core::sc_module_name;
+
+class write_if : virtual public sc_interface
+{
+ public:
+ virtual void write(char) = 0;
+ virtual void reset() = 0;
+ virtual int wtest(int) = 0;
+};
+
+class read_if : virtual public sc_interface
+{
+ public:
+ virtual void read(char &) = 0;
+ virtual int num_available() = 0;
+ virtual int rtest(int) = 0;
+};
+
+class fifo : public sc_channel, public write_if, public read_if
+{
+ public:
+ fifo(sc_module_name name, int size)
+ : sc_channel(name), num_elements(0), first(0), max(size) {
+ data = new char[size];
+ }
+
+ void write(char c) {
+ if (num_elements == max)
+ wait(read_event);
+
+ data[(first + num_elements) % max] = c;
+ ++ num_elements;
+ write_event.notify();
+ }
+
+ void read(char &c){
+ if (num_elements == 0)
+ wait(write_event);
+
+ c = data[first];
+ -- num_elements;
+ first = (first + 1) % max;
+ read_event.notify();
+ }
+
+ int rtest(int size) { return (size <= num_elements) ? 1 : 0; }
+ int wtest(int size) { return (size <= max - num_elements) ? 1 : 0; }
+
+
+ void reset() { num_elements = first = 0; }
+
+ int num_available() { return num_elements;}
+
+ private:
+ int max;
+ char *data;
+ int num_elements, first;
+ sc_event write_event, read_event;
+};
+
+
+#endif
+
+/*
+class producer : public sc_module
+{
+ public:
+ sc_port<write_if> out;
+
+ SC_HAS_PROCESS(producer);
+
+ producer(sc_module_name name) : sc_module(name)
+ {
+ SC_THREAD(main);
+ }
+
+ void main()
+ {
+ const char *str =
+ "Visit www.systemc.org and see what SystemC can do for you today!\n";
+
+ while (*str)
+ out->write(*str++);
+ }
+};
+
+class consumer : public sc_module
+{
+ public:
+ sc_port<read_if> in;
+
+ SC_HAS_PROCESS(consumer);
+
+ consumer(sc_module_name name) : sc_module(name)
+ {
+ SC_THREAD(main);
+ }
+
+ void main()
+ {
+ char c;
+ cout << endl << endl;
+
+ while (true) {
+ in->read(c);
+ cout << c << flush;
+
+ if (in->num_available() == 1)
+ cout << "<1>" << flush;
+ if (in->num_available() == 9)
+ cout << "<9>" << flush;
+ }
+ }
+};
+
+class top : public sc_module
+{
+ public:
+ fifo *fifo_inst;
+ producer *prod_inst;
+ consumer *cons_inst;
+
+ top(sc_module_name name) : sc_module(name)
+ {
+ fifo_inst = new fifo("Fifo1");
+
+ prod_inst = new producer("Producer1");
+ prod_inst->out(*fifo_inst);
+
+ cons_inst = new consumer("Consumer1");
+ cons_inst->in(*fifo_inst);
+ }
+};
+
+int sc_main (int argc , char *argv[]) {
+ top top1("Top1");
+ sc_start(-1);
+ return 0;
+}
+*/
--- /dev/null
+#include "fsm/scd_cont_fsm.h"
+
+#include "scd_logging.h"
+#include "scd_cont_state.h"
+
+
+void scd_cont_fsm::set_state(scd_cont_state& state)
+{
+ _state = &state;
+ scd_debug(_name + ": [" + _state->get_name() +"]");
+}
+
+
+void scd_cont_fsm::save_state()
+{
+ _hist_state = _state;
+}
+
+
+void scd_cont_fsm::save_state(scd_cont_state& state)
+{
+ _hist_state = &state;
+}
+
+
+void scd_cont_fsm::load_state()
+{
+ _state = _hist_state;
+ scd_debug(_name + ": [" + _state->get_name() +"]");
+}
--- /dev/null
+#ifndef SCD_CONT_FSM_H
+#define SCD_CONT_FSM_H
+
+#include <string>
+
+/* forward declaration */
+class scd_cont_state;
+
+
+/**
+ * FSM base class. Holds the current and the history state and allows
+ * state transitions. Transitions are logged in debug loglevel.
+ */
+class scd_cont_fsm
+{
+
+public:
+ /**
+ * Constructor.
+ * \param name the name of the state machine
+ */
+ scd_cont_fsm(const std::string& name): _name(name) {}
+
+ virtual ~scd_cont_fsm() {}
+
+ /**
+ * Sets a new state. This is a state transition.
+ */
+ void set_state(scd_cont_state& state);
+
+ /**
+ * Saves the current state as the history state. This is not a state
+ * transition.
+ */
+ void save_state();
+
+ /**
+ * Saves a specified state as the history state. This is not a state
+ * transition.
+ */
+ void save_state(scd_cont_state& state);
+
+ /**
+ * Restores the saved history state. This is a state transition.
+ */
+ void load_state();
+
+protected:
+ scd_cont_state* _state;
+ scd_cont_state* _hist_state;
+ std::string _name;
+};
+
+#endif
--- /dev/null
+#ifndef SCD_CONT_FSM_IF_H
+#define SCD_CONT_FSM_IF_H
+
+#include "systemc"
+
+
+/**
+ * Public interface for control manager state machines (master, slave, slave
+ * wrapper).
+ */
+class scd_cont_fsm_if
+{
+public:
+ virtual ~scd_cont_fsm_if() {}
+
+ /**
+ * Signalize the FSM that the simulation is idle and the next event
+ * is in a specific amount of time (relative).
+ * \param time time of next event relative to current time
+ */
+ virtual void set_idle(const sc_core::sc_time& time) = 0;
+
+ /**
+ * Signalizes the FSM that the simulation can be run.
+ */
+ virtual void set_busy() = 0;
+
+ /**
+ * Signalizes the FSM that the simulation on this simulator has finished.
+ * No more events exist right now.
+ */
+ virtual void set_done() = 0;
+
+ /**
+ * Signalizes the FSM that an error has occured and the simulation
+ * has to be brought down.
+ */
+ virtual void set_fail() = 0;
+
+ /**
+ * Drives the control FSM. Shall be called repeatedly (i.e. from the
+ * main loop).
+ */
+ virtual void process() = 0;
+
+ /**
+ * Indicates if the FSM is initiated and still working.
+ * \return true if the state is not init, terminated or failed
+ */
+ virtual bool active() const = 0;
+
+ /**
+ * Indicates if another step should be simulated (i.e. the FSM is in
+ * the busy state).
+ * \return true if the FSM is in busy state
+ */
+ virtual bool busy() const = 0;
+
+ /**
+ * Indicates if the FSM is in the failed state.
+ * \return false if an error occured and the FSM stopped working
+ */
+ virtual bool failed() const = 0;
+
+ /**
+ * Indicates if simulation time has to be advanced (i.e. the FSM
+ * is in the time state). If this is the case, the time step
+ * shall be obtained by calling get_time_step().
+ * \return true if the time has to be advanced
+ */
+ virtual bool advance_time() const = 0;
+
+ /**
+ * Returns the time step by which the simulation time has to be advanced.
+ * Shall only be called in time state.
+ */
+ virtual const sc_core::sc_time& get_time_step() = 0;
+};
+
+#endif
--- /dev/null
+#ifndef SCD_CONT_STATE_H
+#define SCD_CONT_STATE_H
+
+#include <string>
+
+#include "scd_simulator.h"
+#include "fsm/scd_cont_fsm_if.h"
+
+
+/* forward declaration */
+class scd_simulator;
+
+
+/**
+ * Base class of all FSM states.
+ */
+class scd_cont_state : public scd_cont_fsm_if
+{
+public:
+ /**
+ * Constructor.
+ * \param sim the simulation environment
+ */
+ scd_cont_state(scd_simulator& sim): _sim(sim) {}
+
+ virtual ~scd_cont_state() {}
+
+ /**
+ * Returns the name of the state.
+ */
+ const std::string& get_name() const { return _name; }
+
+protected:
+ scd_simulator& _sim;
+ std::string _name;
+};
+
+#endif
--- /dev/null
+#ifndef SCD_CONT_WRAPPER_IF_H
+#define SCD_CONT_WRAPPER_IF_H
+
+#include "systemc"
+
+
+/**
+ * Extends the public interface of the slave wrapper FSM.
+ */
+class scd_cont_wrapper_if
+{
+public:
+ /**
+ * Sends a time_req command to the slave.
+ */
+ virtual void send_time_req() = 0;
+
+ /**
+ * Sends a time_nack command to the slave.
+ */
+ virtual void send_time_nack() = 0;
+
+ /**
+ * Sends a time command to the slave.
+ */
+ virtual void send_time(const sc_core::sc_time& time) = 0;
+
+ /**
+ * Sends a term_req command to the slave.
+ */
+ virtual void send_term_req() = 0;
+
+ /**
+ * Sends a term_nack command to the slave.
+ */
+ virtual void send_term_nack() = 0;
+
+ /**
+ * Sends a term command to the slave.
+ */
+ virtual void send_term() = 0;
+
+ /**
+ * Inidcates if the slave is in term_req state.
+ * \return true if the slave seems to be in time_req state
+ */
+ virtual bool time_req() const = 0;
+
+ /**
+ * Inidcates if the slave is in time_ack state.
+ * \return true if the slave seems to be in time_ack state
+ */
+ virtual bool time_ack() const = 0;
+
+ /**
+ * Inidcates if the slave is in term_req state.
+ * \return true if the slave seems to be in term_req state
+ */
+ virtual bool term_req() const = 0;
+
+ /**
+ * Inidcates if the slave is in term_ack state.
+ * \return true if the slave seems to be in term_ack state
+ */
+ virtual bool term_ack() const = 0;
+
+ /**
+ * Inidcates if the slave is in idle state.
+ * \return true if the slave seems to be in idle state
+ */
+ virtual bool idle() const = 0;
+
+ /**
+ * Indicates if the slave is in done state.
+ * \return true if the slave seems to be in done state
+ */
+ virtual bool done() const = 0;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_base.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+#include "scd_command.h"
+#include "scd_cont_man.h"
+
+
+scd_stm_base::scd_stm_base(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_cont_state(sim), _fsm(fsm), _slaves(fsm._slaves),
+ _time_step(fsm._time_step),
+ _st_init(fsm._st_init), _st_busy(fsm._st_busy), _st_idle(fsm._st_idle),
+ _st_done(fsm._st_done), _st_time_req(fsm._st_time_req),
+ _st_time(fsm._st_time), _st_term_req(fsm._st_term_req),
+ _st_terminate(fsm._st_terminate), _st_terminated(fsm._st_terminated),
+ _st_fail(fsm._st_fail), _st_failed(fsm._st_failed)
+{
+}
+
+
+void scd_stm_base::set_fail()
+{
+ std::list<scd_cont_slave_wrapper*>::iterator it;
+
+ for (it = _slaves.begin(); it != _slaves.end(); it++)
+ {
+ (*it)->set_fail();
+ }
+
+ _fsm.set_state(_st_fail);
+} // set_fail()
+
+
+void scd_stm_base::process()
+{
+ // check for failed slaves and react
+ if (!_check_slaves())
+ return;
+}
+
+
+bool scd_stm_base::active() const { return true; }
+
+
+bool scd_stm_base::busy() const { return false; }
+
+
+bool scd_stm_base::failed() const { return false; }
+
+
+bool scd_stm_base::advance_time() const { return false; }
+
+
+const sc_core::sc_time& scd_stm_base::get_time_step()
+{
+ scd_error("illegal call to get_time_step()");
+ throw scd_exception("illegal call");
+}
+
+
+bool scd_stm_base::_check_slaves()
+{
+
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ {
+ if ( (*iter)->failed() )
+ {
+ scd_error("slave \"" + (*iter)->get_name() + "\" failed");
+ set_fail();
+ return false;
+ }
+ }
+
+ return true;
+
+} // _check_slaves()
+
+
+bool scd_stm_base::_some_slaves_active()
+{
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ {
+ if ( (*iter)->active() )
+ return true;
+ }
+
+ return false;
+
+} // _some_slaves_active()
+
+
+void scd_stm_base::_close_slaves()
+{
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ (*iter)->close();
+}
--- /dev/null
+#ifndef SCD_STM_BASE_H
+#define SCD_STM_BASE_H
+
+#include <list>
+
+#include "scd_simulator.h"
+#include "scd_cont_slave_wrapper.h"
+#include "fsm/scd_cont_state.h"
+
+
+/* forward declaration */
+class scd_cont_man_master;
+
+
+/**
+ * Base class for all control master states.
+ */
+class scd_stm_base : public scd_cont_state
+{
+public:
+ /**
+ * Constructor.
+ * \param sim the simulation environment
+ * \param fsm the FSM of this state
+ */
+ scd_stm_base(scd_simulator& sim, scd_cont_man_master& fsm);
+
+ virtual ~scd_stm_base() {}
+
+ /* scd_cont_fsm_if */
+ void set_busy() {}
+ void set_idle(const sc_core::sc_time& time) {}
+ void set_done() {}
+ void set_fail();
+ void process();
+ bool active() const;
+ bool busy() const;
+ bool failed() const;
+ bool advance_time() const;
+ const sc_core::sc_time& get_time_step();
+
+protected:
+ scd_cont_man_master& _fsm;
+ std::list<scd_cont_slave_wrapper*>& _slaves;
+ sc_core::sc_time& _time_step;
+ scd_cont_state& _st_init;
+ scd_cont_state& _st_busy;
+ scd_cont_state& _st_idle;
+ scd_cont_state& _st_done;
+ scd_cont_state& _st_time_req;
+ scd_cont_state& _st_time;
+ scd_cont_state& _st_term_req;
+ scd_cont_state& _st_terminate;
+ scd_cont_state& _st_terminated;
+ scd_cont_state& _st_fail;
+ scd_cont_state& _st_failed;
+
+ /* member functions */
+ bool _check_slaves();
+ bool _some_slaves_active();
+ void _close_slaves();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_busy.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+void scd_stm_busy::set_idle(const sc_core::sc_time& time)
+{
+ /* prevents the situation where no events exist, but a huge
+ * ammount of data is being transferred that will generate events later
+ */
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ return;
+
+ _time_step = time;
+ _fsm.set_state(_st_idle);
+}
+
+
+void scd_stm_busy::set_done()
+{
+ /* prevents the situation where no events exist, but a huge
+ * ammount of data is being transferred that will generate events later
+ */
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ return;
+
+ _time_step = sc_core::SC_ZERO_TIME;
+ _fsm.set_state(_st_done);
+}
+
+
+bool scd_stm_busy::busy() const { return true; }
--- /dev/null
+#ifndef SCD_STM_BUSY_H
+#define SCD_STM_BUSY_H
+
+#include "fsm/scd_stm_base.h"
+
+
+class scd_stm_busy : public scd_stm_base
+{
+public:
+ scd_stm_busy(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "busy"; }
+ virtual ~scd_stm_busy() {}
+
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& time);
+ void set_done();
+ bool busy() const;
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_done.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+void scd_stm_done::set_busy()
+{
+ _fsm.set_state(_st_busy);
+}
+
+
+void scd_stm_done::set_idle(const sc_core::sc_time& time)
+{
+ _time_step = time;
+ _fsm.set_state(_st_idle);
+}
+
+
+void scd_stm_done::process()
+{
+ if (!_check_slaves())
+ return;
+
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+ bool terminate = true;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ {
+ if (!(*iter)->idle() && !(*iter)->done())
+ {
+ // this slave is not ready yet
+ return;
+ }
+
+ if (!(*iter)->done())
+ terminate = false;
+ }
+
+ /* all slaves seem idle or done. wait a short moment, to prevent
+ * race conditions (channel data in transit but both endpoints done).
+ * if no socket activity occured we can move on, else we cancel.
+ */
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ return;
+
+ if (terminate)
+ {
+ // all slaves seem to be done
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ (*iter)->send_term_req();
+ _fsm.save_state();
+ _fsm.set_state(_st_term_req);
+ }
+ else
+ {
+ // some slaves are not done yet
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ (*iter)->send_time_req();
+ _fsm.save_state();
+ _fsm.set_state(_st_time_req);
+ }
+}
--- /dev/null
+#ifndef SCD_STM_DONE_H
+#define SCD_STM_DONE_H
+
+#include "fsm/scd_stm_base.h"
+
+
+class scd_stm_done : public scd_stm_base
+{
+public:
+ scd_stm_done(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "done"; }
+ virtual ~scd_stm_done() {}
+
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_idle(const sc_core::sc_time& time);
+ void process();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_fail.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+void scd_stm_fail::process()
+{
+ if (!_some_slaves_active())
+ {
+ // all slaves have terminated
+ _sim.get_chan_man().close();
+ _close_slaves();
+ _fsm.set_state(_st_failed);
+ }
+}
--- /dev/null
+#ifndef SCD_STM_FAIL_H
+#define SCD_STM_FAIL_H
+
+#include "fsm/scd_stm_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_master;
+
+
+class scd_stm_fail : public scd_stm_base
+{
+public:
+ scd_stm_fail(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "fail"; }
+
+ virtual ~scd_stm_fail() {}
+
+
+ /* scd_cont_fsm_if */
+ void set_fail() {}
+ void process();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_failed.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+bool scd_stm_failed::active() const { return false; }
+
+
+bool scd_stm_failed::failed() const { return true; }
--- /dev/null
+#ifndef SCD_STM_FAILED_H
+#define SCD_STM_FAILED_H
+
+#include "fsm/scd_stm_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_master;
+
+
+class scd_stm_failed : public scd_stm_base
+{
+public:
+ scd_stm_failed(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "failed"; }
+ virtual ~scd_stm_failed() {}
+
+ /* scd_cont_fsm_if */
+ void set_fail() {}
+ void process() {}
+ bool active() const;
+ bool failed() const;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_idle.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+void scd_stm_idle::set_busy()
+{
+ _fsm.set_state(_st_busy);
+}
+
+
+void scd_stm_idle::set_done()
+{
+ _time_step = sc_core::SC_ZERO_TIME;
+ _fsm.set_state(_st_done);
+}
+
+
+void scd_stm_idle::process()
+{
+ if (!_check_slaves())
+ return;
+
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ {
+ if (!(*iter)->idle() && !(*iter)->done())
+ {
+ // this slave is not ready yet
+ return;
+ }
+ }
+
+ /* all slaves seem idle or done. wait a short moment, to prevent
+ * race conditions (channel data in transit but both endpoints done).
+ * if no socket activity occured we can move on, else we cancel.
+ */
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ return;
+
+ // all slaves seem to be ready to advance time
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ (*iter)->send_time_req();
+
+ _fsm.save_state();
+ _fsm.set_state(_st_time_req);
+}
--- /dev/null
+#ifndef SCD_STM_IDLE_H
+#define SCD_STM_IDLE_H
+
+#include "fsm/scd_stm_base.h"
+
+
+class scd_stm_idle : public scd_stm_base
+{
+public:
+ scd_stm_idle(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "idle"; }
+ virtual ~scd_stm_idle() {}
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_done();
+ void process();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_init.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+void scd_stm_init::set_idle(const sc_core::sc_time& time)
+{
+ scd_error("init: illegal call to set_idle()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stm_init::set_busy()
+{
+ scd_error("init: illegal call to set_busy()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stm_init::set_done()
+{
+ scd_error("init: illegal call to set_done()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stm_init::process()
+{
+ // check for failed slaves and react
+ if (!_check_slaves())
+ return;
+
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ {
+ // if this is still in init state we terminate
+ if ( !(*iter)->active() )
+ return;
+ }
+
+ // all slaves are active
+ scd_info("all slaves connected");
+ _fsm.set_state(_st_busy);
+
+} // process()
+
+
+bool scd_stm_init::active() const { return false; }
+
+
+bool scd_stm_init::advance_time() const
+{
+ scd_error("illegal call to advance_time()");
+ throw scd_exception("illegal call");
+}
--- /dev/null
+#ifndef SCD_STM_INIT_H
+#define SCD_STM_INIT_H
+
+#include "fsm/scd_stm_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_master;
+
+
+class scd_stm_init : public scd_stm_base
+{
+public:
+ scd_stm_init(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "init"; }
+ virtual ~scd_stm_init() {}
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& time);
+ void set_busy();
+ void set_done();
+ void process();
+ bool active() const;
+ bool advance_time() const;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_term_req.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+void scd_stm_term_req::set_busy()
+{
+ _send_term_nack();
+ _fsm.load_state();
+}
+
+
+void scd_stm_term_req::set_idle(const sc_core::sc_time& time)
+{
+ _send_term_nack();
+ _fsm.load_state();
+}
+
+
+void scd_stm_term_req::process()
+{
+ if (!_check_slaves())
+ return;
+
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ {
+ if ( !(*iter)->term_req() && !(*iter)->term_ack() )
+ {
+ // received term_nack from this slave
+ _send_term_nack();
+ _fsm.load_state();
+ return;
+ }
+ else if ( !(*iter)->term_ack() )
+ {
+ // this slave did not respond yet
+ return;
+ }
+ }
+
+ // all slaves acknkowledged
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ (*iter)->send_term();
+
+ _fsm.set_state(_st_terminate);
+}
+
+
+void scd_stm_term_req::_send_term_nack()
+{
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ (*iter)->send_term_nack();
+}
--- /dev/null
+#ifndef SCD_STM_TERM_REQ_H
+#define SCD_STM_TERM_REQ_H
+
+#include "fsm/scd_stm_base.h"
+
+
+class scd_stm_term_req : public scd_stm_base
+{
+public:
+ scd_stm_term_req(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "term_req"; }
+ virtual ~scd_stm_term_req() {}
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_idle(const sc_core::sc_time& time);
+ void process();
+
+private:
+ void _send_term_nack();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_terminate.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+void scd_stm_terminate::set_busy()
+{
+ scd_error("received further events while terminating");
+ set_fail();
+}
+
+
+void scd_stm_terminate::set_idle(const sc_core::sc_time& time)
+{
+ scd_error("received future events while terminating");
+ set_fail();
+}
+
+
+void scd_stm_terminate::process()
+{
+ // check for failed slaves and react
+ if (!_check_slaves())
+ return;
+
+ if (_some_slaves_active())
+ {
+ // not all slaves have terminated yet
+ return;
+ }
+ else
+ {
+ // all slaves terminated
+ _sim.get_chan_man().close();
+ _close_slaves();
+ _fsm.set_state(_st_terminated);
+ }
+}
--- /dev/null
+#ifndef SCD_STM_TERMINATE_H
+#define SCD_STM_TERMINATE_H
+
+#include "fsm/scd_stm_base.h"
+
+
+class scd_stm_terminate : public scd_stm_base
+{
+public:
+ scd_stm_terminate(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "terminate"; }
+ virtual ~scd_stm_terminate() {}
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_idle(const sc_core::sc_time& time);
+ void process();
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_terminated.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+bool scd_stm_terminated::active() const { return false; }
--- /dev/null
+#ifndef SCD_STM_TERMINATED_H
+#define SCD_STM_TERMINATED_H
+
+#include "fsm/scd_stm_base.h"
+
+
+class scd_stm_terminated : public scd_stm_base
+{
+public:
+ scd_stm_terminated(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "terminated"; }
+ virtual ~scd_stm_terminated() {}
+
+ /* scd_cont_fsm_if */
+ void set_fail() {}
+ void process() {}
+ bool active() const;
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_time.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+bool scd_stm_time::advance_time() const { return true; }
+
+
+const sc_core::sc_time& scd_stm_time::get_time_step()
+{
+ _fsm.set_state(_st_busy);
+ return _time_step;
+}
--- /dev/null
+#ifndef SCD_STM_TIME_H
+#define SCD_STM_TIME_H
+
+#include "fsm/scd_stm_base.h"
+
+
+class scd_stm_time : public scd_stm_base
+{
+public:
+ scd_stm_time(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "time"; }
+ virtual ~scd_stm_time() {}
+
+ /* scd_cont_fsm_if */
+ bool advance_time() const;
+ const sc_core::sc_time& get_time_step();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stm_time_req.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_master.h"
+
+
+void scd_stm_time_req::set_busy()
+{
+ _send_time_nack();
+ _fsm.load_state();
+}
+
+
+void scd_stm_time_req::process()
+{
+ if (!_check_slaves())
+ return;
+
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+ sc_core::sc_time min_step = _time_step;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ {
+ if ( !(*iter)->time_req() && !(*iter)->time_ack() )
+ {
+ // received time_nack from this slave
+ _send_time_nack();
+ _fsm.load_state();
+ return;
+ }
+ else if ( !(*iter)->time_ack() )
+ {
+ // this slave did not respond yet
+ return;
+ }
+ else
+ {
+ // received time_ack => search the smallest step
+ sc_core::sc_time time_slave = (*iter)->get_time_step();
+ if (min_step == sc_core::SC_ZERO_TIME)
+ min_step = time_slave;
+ else if (min_step > time_slave &&
+ time_slave != sc_core::SC_ZERO_TIME)
+ min_step = time_slave;
+ }
+ }
+
+ // all slaves acknkowledged
+ _time_step = min_step;
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ (*iter)->send_time(min_step);
+
+ _fsm.set_state(_st_time);
+}
+
+
+void scd_stm_time_req::_send_time_nack()
+{
+ std::list<scd_cont_slave_wrapper*>::iterator iter;
+
+ for (iter = _slaves.begin(); iter != _slaves.end(); iter++)
+ (*iter)->send_time_nack();
+}
--- /dev/null
+#ifndef SCD_STM_TIME_REQ_H
+#define SCD_STM_TIME_REQ_H
+
+#include "fsm/scd_stm_base.h"
+
+
+class scd_stm_time_req : public scd_stm_base
+{
+public:
+ scd_stm_time_req(scd_simulator& sim, scd_cont_man_master& fsm):
+ scd_stm_base(sim, fsm) { _name = "time_req"; }
+ virtual ~scd_stm_time_req() {}
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void process();
+
+private:
+ void _send_time_nack();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_base.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+#include "scd_command.h"
+#include "scd_cont_man.h"
+
+
+
+scd_sts_base::scd_sts_base(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_cont_state(sim), _fsm(fsm),
+ _st_init(fsm._st_init), _st_busy(fsm._st_busy), _st_idle(fsm._st_idle),
+ _st_done(fsm._st_done), _st_time_ack(fsm._st_time_ack),
+ _st_time(fsm._st_time), _st_term_ack(fsm._st_term_ack),
+ _st_terminated(fsm._st_terminated), _st_fail(fsm._st_fail),
+ _st_failed(fsm._st_failed),
+ _writer(fsm._writer), _reader(fsm._reader), _connector(fsm._connector)
+{
+}
+
+
+void scd_sts_base::set_failed()
+{
+ _sim.get_poller().remove_handler(_fsm);
+ _sim.get_chan_man().close();
+ _fsm.set_state(_st_failed);
+}
+
+
+void scd_sts_base::recv_time_req()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_NACK);
+ _fsm.send_command(cmd);
+}
+
+
+void scd_sts_base::recv_time(const sc_core::sc_time& time)
+{
+ scd_warn("received time message in wrong state");
+}
+
+
+void scd_sts_base::recv_term_req()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TERM_NACK);
+ _fsm.send_command(cmd);
+}
+
+
+void scd_sts_base::recv_term()
+{
+ scd_warn("received terminate message in wrong state");
+}
+
+
+void scd_sts_base::set_fail()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_FAILED);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_fail);
+}
+
+
+bool scd_sts_base::active() const { return true; }
+
+
+bool scd_sts_base::busy() const { return false; }
+
+
+bool scd_sts_base::failed() const { return false; }
+
+
+bool scd_sts_base::advance_time() const { return false; }
+
+
+const sc_core::sc_time& scd_sts_base::get_time_step()
+{
+ scd_warn("illegal call to get_time_step()");
+ throw scd_exception("illegal call");
+}
--- /dev/null
+#ifndef SCD_STS_BASE_H
+#define SCD_STS_BASE_H
+
+#include "scd_simulator.h"
+#include "scd_out_connector.h"
+#include "scd_command_writer.h"
+#include "scd_command_reader.h"
+#include "fsm/scd_cont_state.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+/**
+ * Base class for all control slave states.
+ */
+class scd_sts_base : public scd_cont_state
+{
+public:
+ /**
+ * Constructor.
+ * \param sim the simulation environment
+ * \param fsm the FSM of this state
+ */
+ scd_sts_base(scd_simulator& sim, scd_cont_man_slave& fsm);
+
+ virtual ~scd_sts_base() {}
+
+ /**
+ * Signalizes the state, that a failed message has been received
+ * from the master.
+ */
+ virtual void set_failed();
+
+ /**
+ * Signalizes the state, that a time_req message has been received
+ * from the master.
+ */
+ virtual void recv_time_req();
+
+ /**
+ * Signalizes the state, that a time_nack message has been received
+ * from the master.
+ */
+ virtual void recv_time_nack() {}
+
+ /**
+ * Signalizes the state, that a time message has been received
+ * from the master.
+ */
+ virtual void recv_time(const sc_core::sc_time& time);
+
+ /**
+ * Signalizes the state, that a term_req message has been received
+ * from the master.
+ */
+ virtual void recv_term_req();
+
+ /**
+ * Signalizes the state, that a term_nack message has been received
+ * from the master.
+ */
+ virtual void recv_term_nack() {}
+
+ /**
+ * Signalizes the state, that a term message has been received
+ * from the master.
+ */
+ virtual void recv_term();
+
+ /* scd_cont_fsm_if */
+ void set_busy() {}
+ void set_idle(const sc_core::sc_time& time) {}
+ void set_done() {}
+ void set_fail();
+ void process() {}
+ bool active() const;
+ bool busy() const;
+ bool failed() const;
+ bool advance_time() const;
+ const sc_core::sc_time& get_time_step();
+
+protected:
+ scd_cont_man_slave& _fsm;
+ scd_command_writer& _writer;
+ scd_command_reader& _reader;
+ scd_out_connector& _connector;
+ scd_cont_state& _st_init;
+ scd_cont_state& _st_busy;
+ scd_cont_state& _st_idle;
+ scd_cont_state& _st_done;
+ scd_cont_state& _st_time_ack;
+ scd_cont_state& _st_time;
+ scd_cont_state& _st_term_ack;
+ scd_cont_state& _st_terminated;
+ scd_cont_state& _st_fail;
+ scd_cont_state& _st_failed;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_busy.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+
+
+void scd_sts_busy::set_idle(const sc_core::sc_time& time)
+{
+ /* prevents the situation where no events exist, but a huge
+ * ammount of data is being transferred that will generate events later
+ */
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ return;
+
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_IDLE, time);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_idle);
+}
+
+
+void scd_sts_busy::set_done()
+{
+ /* prevents the situation where no events exist, but a huge
+ * ammount of data is being transferred that will generate events later
+ */
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ return;
+
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_DONE);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_done);
+}
+
+
+bool scd_sts_busy::busy() const { return true; }
--- /dev/null
+#ifndef SCD_STS_BUSY_H
+#define SCD_STS_BUSY_H
+
+#include "fsm/scd_sts_base.h"
+
+
+class scd_sts_busy : public scd_sts_base
+{
+public:
+ scd_sts_busy(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "busy"; }
+ virtual ~scd_sts_busy() {}
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& time);
+ void set_done();
+ bool busy() const;
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_done.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+#include "scd_cont_man.h"
+
+
+void scd_sts_done::recv_time_req()
+{
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ {
+ // had activity on sockets => we might be receiving data
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_NACK);
+ _fsm.send_command(cmd);
+ }
+ else
+ {
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_ACK);
+ _fsm.send_command(cmd);
+ _fsm.save_state();
+ _fsm.set_state(_st_time_ack);
+ }
+}
+
+
+void scd_sts_done::recv_term_req()
+{
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ {
+ // had activity on sockets => we might be receiving data
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TERM_NACK);
+ _fsm.send_command(cmd);
+ }
+ else
+ {
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TERM_ACK);
+ _fsm.send_command(cmd);
+ _fsm.save_state();
+ _fsm.set_state(_st_term_ack);
+ }
+}
+
+
+void scd_sts_done::set_idle(const sc_core::sc_time& time)
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_IDLE, time);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_idle);
+}
+
+
+void scd_sts_done::set_busy()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_BUSY);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_busy);
+}
--- /dev/null
+#ifndef SCD_STS_DONE_H
+#define SCD_STS_DONE_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_done : public scd_sts_base
+{
+public:
+ scd_sts_done(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "done"; }
+ virtual ~scd_sts_done() {}
+
+ void recv_time_req();
+ void recv_term_req();
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& time);
+ void set_busy();
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_fail.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+
+
+void scd_sts_fail::process()
+{
+ if (!_fsm.is_sending())
+ {
+ _sim.get_poller().remove_handler(_fsm);
+ _sim.get_chan_man().close();
+ _fsm.close();
+ _fsm.set_state(_st_failed);
+ }
+}
--- /dev/null
+#ifndef SCD_STS_FAIL_H
+#define SCD_STS_FAIL_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_fail : public scd_sts_base
+{
+public:
+ scd_sts_fail(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "fail"; }
+ virtual ~scd_sts_fail() {}
+
+ void recv_time_req() {}
+ void recv_time(const sc_core::sc_time& time) {}
+ void recv_term_req() {}
+ void recv_term() {}
+
+ /* scd_cont_fsm_if */
+ void set_fail() {}
+ void process();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_failed.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+
+bool scd_sts_failed::active() const { return false; }
+
+
+bool scd_sts_failed::failed() const { return true; }
--- /dev/null
+#ifndef SCD_STS_FAILED_H
+#define SCD_STS_FAILED_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_failed : public scd_sts_base
+{
+public:
+ scd_sts_failed(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "failed"; }
+ virtual ~scd_sts_failed() {}
+
+ void set_failed() {}
+
+ void recv_time_req() {}
+ void recv_time(const sc_core::sc_time& time) {}
+ void recv_term_req() {}
+ void recv_term() {}
+
+ /* scd_cont_fsm_if */
+ void set_fail() {}
+ bool active() const;
+ bool failed() const;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_idle.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+
+
+void scd_sts_idle::recv_time_req()
+{
+ if (_sim.get_poller().wait(SCD_CONT_DELAY))
+ {
+ // had activity on sockets => we might be receiving data
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_NACK);
+ _fsm.send_command(cmd);
+ }
+ else
+ {
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_ACK);
+ _fsm.send_command(cmd);
+ _fsm.save_state();
+ _fsm.set_state(_st_time_ack);
+ }
+}
+
+
+void scd_sts_idle::set_busy()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_BUSY);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_busy);
+}
+
+
+void scd_sts_idle::set_done()
+{
+ scd_warn("slave: transition attempt from idle to done");
+}
--- /dev/null
+#ifndef SCD_STS_IDLE_H
+#define SCD_STS_IDLE_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_idle : public scd_sts_base
+{
+public:
+ scd_sts_idle(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "idle"; }
+ virtual ~scd_sts_idle() {}
+
+ void recv_time_req();
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_done();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_init.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+
+
+void scd_sts_init::set_failed()
+{
+ _fsm.set_state(_st_failed);
+}
+
+
+void scd_sts_init::set_idle(const sc_core::sc_time& time)
+{
+ scd_error("init: illegal call to set_idle()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_sts_init::set_busy()
+{
+ scd_error("init: illegal call to set_busy()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_sts_init::set_done()
+{
+ scd_error("init: illegal call to set_done()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_sts_init::set_fail()
+{
+ _fsm.set_state(_st_failed);
+}
+
+
+void scd_sts_init::process()
+{
+ _connector.process();
+
+ if (!_connector.is_connecting() && !_connector.has_connection())
+ {
+ // unable to connect to master
+ scd_error("connecting to master failed");
+ _fsm.set_state(_st_failed);
+ }
+ else if (!_connector.is_connecting() && _connector.has_connection())
+ {
+ // successfully connected to master
+ scd_info("connected to master");
+ _fsm.set_socket();
+ _sim.get_poller().register_handler(_fsm, SOCK_EV_READ | SOCK_EV_CLOSE);
+ _fsm.set_state(_st_busy);
+ }
+
+} // process()
+
+
+bool scd_sts_init::active() const { return false; }
+
+
+bool scd_sts_init::advance_time() const
+{
+ scd_error("illegal call to advance_time()");
+ throw scd_exception("illegal call");
+}
--- /dev/null
+#ifndef SCD_STS_INIT_H
+#define SCD_STS_INIT_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_init : public scd_sts_base
+{
+public:
+ scd_sts_init(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "init"; }
+ virtual ~scd_sts_init() {}
+
+ void set_failed();
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& time);
+ void set_busy();
+ void set_done();
+ void set_fail();
+ void process();
+ bool active() const;
+ bool advance_time() const;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_term_ack.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+
+
+void scd_sts_term_ack::recv_time_req()
+{
+ scd_warn("received time request in illegal state");
+}
+
+
+void scd_sts_term_ack::recv_term_req()
+{
+ scd_warn("received terminate request in illegal state");
+}
+
+
+void scd_sts_term_ack::recv_term_nack()
+{
+ _fsm.load_state();
+}
+
+
+void scd_sts_term_ack::recv_term()
+{
+ _sim.get_poller().remove_handler(_fsm);
+ _fsm.set_state(_st_terminated);
+}
+
+
+void scd_sts_term_ack::set_busy()
+{
+ scd_warn("received channel data while synchronizing to terminate");
+}
--- /dev/null
+#ifndef SCD_STS_TERM_ACK_H
+#define SCD_STS_TERM_ACK_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_term_ack : public scd_sts_base
+{
+public:
+ scd_sts_term_ack(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "term_ack"; }
+ virtual ~scd_sts_term_ack() {}
+
+ void recv_time_req();
+ void recv_term_req();
+ void recv_term_nack();
+ void recv_term();
+
+ void set_fail() {}
+ void set_busy();
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_terminated.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+void scd_sts_terminated::set_busy()
+{
+ scd_error("received further events while synchronizing (terminate)");
+}
+
+
+void scd_sts_terminated::set_idle(const sc_core::sc_time& time)
+{
+ scd_error("received future events while synchronizing (terminate)");
+}
+
+
+bool scd_sts_terminated::active() const { return false; }
--- /dev/null
+#ifndef SCD_STS_TERMINATED_H
+#define SCD_STS_TERMINATED_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_terminated : public scd_sts_base
+{
+public:
+ scd_sts_terminated(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "terminated"; }
+ virtual ~scd_sts_terminated() {}
+
+ void set_failed() {}
+ void recv_time_req() {}
+ void recv_term_req() {}
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_idle(const sc_core::sc_time& time);
+ void set_fail() {}
+ bool active() const;
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_time.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+
+
+void scd_sts_time::set_time_step(const sc_core::sc_time& time)
+{
+ _time_step = time;
+}
+
+
+bool scd_sts_time::advance_time() const { return true; }
+
+
+const sc_core::sc_time& scd_sts_time::get_time_step()
+{
+ _fsm.set_state(_st_busy);
+ return _time_step;
+}
--- /dev/null
+#ifndef SCD_STS_TIME_H
+#define SCD_STS_TIME_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_time : public scd_sts_base
+{
+public:
+ scd_sts_time(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "time"; }
+ virtual ~scd_sts_time() {}
+
+ void set_time_step(const sc_core::sc_time& time);
+
+ /* scd_cont_fsm_if */
+ bool advance_time() const;
+ const sc_core::sc_time& get_time_step();
+
+private:
+ sc_core::sc_time _time_step;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_sts_time_ack.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_man_slave.h"
+
+
+void scd_sts_time_ack::recv_time_req()
+{
+ scd_warn("received time request in wrong state");
+}
+
+
+void scd_sts_time_ack::recv_time_nack()
+{
+ _fsm.load_state();
+}
+
+
+void scd_sts_time_ack::recv_time(const sc_core::sc_time& time)
+{
+ static_cast<scd_sts_time&>(_st_time).set_time_step(time);
+ _fsm.set_state(_st_time);
+}
+
+
+void scd_sts_time_ack::recv_term_req()
+{
+ scd_warn("received terminate request in wrong state");
+}
+
+
+void scd_sts_time_ack::set_busy()
+{
+ scd_warn("received channel data while synchronizing to terminate");
+}
--- /dev/null
+#ifndef SCD_STS_TIME_ACK_H
+#define SCD_STS_TIME_ACK_H
+
+#include "fsm/scd_sts_base.h"
+
+
+/* forward declaration */
+class scd_cont_man_slave;
+
+
+class scd_sts_time_ack : public scd_sts_base
+{
+public:
+ scd_sts_time_ack(scd_simulator& sim, scd_cont_man_slave& fsm):
+ scd_sts_base(sim, fsm) { _name = "time_ack"; }
+ virtual ~scd_sts_time_ack() {}
+
+ /* scd_sts_base */
+ void recv_time_req();
+ void recv_time_nack();
+ void recv_time(const sc_core::sc_time& time);
+ void recv_term_req();
+
+ void set_busy();
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_base.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+#include "scd_command.h"
+
+
+scd_stsw_base::scd_stsw_base(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_cont_state(sim), _fsm(fsm), _time_step(fsm._time_step),
+ _st_init(fsm._st_init), _st_busy(fsm._st_busy), _st_idle(fsm._st_idle),
+ _st_done(fsm._st_done), _st_time_req(fsm._st_time_req),
+ _st_time_ack(fsm._st_time_ack), _st_term_req(fsm._st_term_req),
+ _st_term_ack(fsm._st_term_ack), _st_terminate(fsm._st_terminate),
+ _st_terminated(fsm._st_terminated), _st_fail(fsm._st_fail),
+ _st_failed(fsm._st_failed)
+{
+}
+
+
+void scd_stsw_base::set_connected()
+{
+ scd_warn("illegal call to set_connected()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_base::set_failed()
+{
+ _sim.get_poller().remove_handler(_fsm);
+ _fsm.set_state(_st_failed);
+}
+
+
+void scd_stsw_base::send_time_req()
+{
+ scd_warn("illegal call to send_time_req()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_base::send_time(const sc_core::sc_time& time)
+{
+ scd_warn("illegal call to send_time()");
+ throw scd_exception("illegal call");
+}
+
+void scd_stsw_base::send_term_req()
+{
+ scd_warn("illegal call to send_term_req()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_base::send_term()
+{
+ scd_warn("illegal call to send_term()");
+ throw scd_exception("illegal call");
+}
+
+
+bool scd_stsw_base::time_req() const { return false; }
+
+
+bool scd_stsw_base::time_ack() const { return false; }
+
+
+bool scd_stsw_base::term_req() const { return false; }
+
+
+bool scd_stsw_base::term_ack() const { return false; }
+
+
+bool scd_stsw_base::idle() const { return false; }
+
+
+bool scd_stsw_base::done() const { return false; }
+
+
+void scd_stsw_base::set_busy()
+{
+ scd_error("illegal call to set_busy()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_base::set_idle(const sc_core::sc_time& time)
+{
+ scd_error("illegal call to set_idle()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_base::set_done()
+{
+ scd_error("illegal call to set_done()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_base::set_fail()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_FAILED);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_fail);
+}
+
+
+bool scd_stsw_base::active() const { return true; }
+
+
+bool scd_stsw_base::busy() const { return false; }
+
+
+bool scd_stsw_base::failed() const { return false; }
+
+
+bool scd_stsw_base::advance_time() const { return false; }
+
+
+const sc_core::sc_time& scd_stsw_base::get_time_step()
+{
+ scd_error("illegal call to get_time_step()");
+ throw scd_exception("illegal call");
+}
--- /dev/null
+#ifndef SCD_STSW_BASE_H
+#define SCD_STSW_BASE_H
+
+#include "scd_simulator.h"
+#include "fsm/scd_cont_state.h"
+#include "fsm/scd_cont_wrapper_if.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+/**
+ * Base class for all control slave wrapper states.
+ */
+class scd_stsw_base : public scd_cont_state, public scd_cont_wrapper_if
+{
+public:
+ /**
+ * Constructor.
+ * \param sim the simulation environment
+ * \param fsm the FSM of this state
+ */
+ scd_stsw_base(scd_simulator& sim, scd_cont_slave_wrapper& fsm);
+
+ virtual ~scd_stsw_base() {}
+
+ /**
+ * Signalizes the state that the slave has been connected to the wrapper.
+ */
+ virtual void set_connected();
+
+ /**
+ * Signalizes the state that a failed command has been received
+ * from the slave.
+ */
+ virtual void set_failed();
+
+ /**
+ * Signalizes the state that a time_nack command has been received
+ * from the slave.
+ */
+ virtual void recv_time_nack() {}
+
+ /**
+ * Signalizes the state that a time_ack command has been received
+ * from the slave.
+ */
+ virtual void recv_time_ack() {}
+
+ /**
+ * Signalizes the state that a term_nack command has been received
+ * from the slave.
+ */
+ virtual void recv_term_nack() {}
+
+ /**
+ * Signalizes the state that a term_ack command has been received
+ * from the slave.
+ */
+ virtual void recv_term_ack() {}
+
+ /* scd_cont_wrapper_if */
+ void send_time_req();
+ void send_time_nack() {}
+ void send_time(const sc_core::sc_time& time);
+ void send_term_req();
+ void send_term_nack() {};
+ void send_term();
+ bool time_req() const;
+ bool time_ack() const;
+ bool term_req() const;
+ bool term_ack() const;
+ bool idle() const;
+ bool done() const;
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_idle(const sc_core::sc_time& time);
+ void set_done();
+ void set_fail();
+ void process() {};
+ bool active() const;
+ bool busy() const;
+ bool failed() const;
+ bool advance_time() const;
+ const sc_core::sc_time& get_time_step();
+
+protected:
+ scd_cont_slave_wrapper& _fsm;
+ sc_core::sc_time& _time_step;
+ scd_cont_state& _st_init;
+ scd_cont_state& _st_busy;
+ scd_cont_state& _st_idle;
+ scd_cont_state& _st_done;
+ scd_cont_state& _st_time_req;
+ scd_cont_state& _st_time_ack;
+ scd_cont_state& _st_term_req;
+ scd_cont_state& _st_term_ack;
+ scd_cont_state& _st_terminate;
+ scd_cont_state& _st_terminated;
+ scd_cont_state& _st_fail;
+ scd_cont_state& _st_failed;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_busy.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_busy::set_idle(const sc_core::sc_time& time)
+{
+ _time_step = time;
+ _fsm.set_state(_st_idle);
+}
+
+
+void scd_stsw_busy::set_done()
+{
+ _time_step = sc_core::SC_ZERO_TIME;
+ _fsm.set_state(_st_done);
+}
+
+
+bool scd_stsw_busy::busy() const { return true; }
--- /dev/null
+#ifndef SCD_STSW_BUSY_H
+#define SCD_STSW_BUSY_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+class scd_stsw_busy : public scd_stsw_base
+{
+public:
+ scd_stsw_busy(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "busy"; }
+ virtual ~scd_stsw_busy() {}
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& time);
+ void set_done();
+ bool busy() const;
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_done.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_done::send_time_req()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_REQ);
+ _fsm.send_command(cmd);
+ _fsm.save_state();
+ _fsm.set_state(_st_time_req);
+}
+
+
+void scd_stsw_done::send_term_req()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TERM_REQ);
+ _fsm.send_command(cmd);
+ _fsm.save_state();
+ _fsm.set_state(_st_term_req);
+}
+
+
+bool scd_stsw_done::done() const { return true; }
+
+
+void scd_stsw_done::set_busy()
+{
+ _fsm.set_state(_st_busy);
+}
+
+
+void scd_stsw_done::set_idle(const sc_core::sc_time& time)
+{
+ _time_step = time;
+ _fsm.set_state(_st_idle);
+}
--- /dev/null
+#ifndef SCD_STSW_DONE_H
+#define SCD_STSW_DONE_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_done : public scd_stsw_base
+{
+public:
+ scd_stsw_done(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "done"; }
+ virtual ~scd_stsw_done() {}
+
+ /* scd_cont_wrapper_if */
+ void send_time_req();
+ void send_term_req();
+ bool done() const;
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_idle(const sc_core::sc_time& time);
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_fail.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_fail::set_fail() {}
+
+
+void scd_stsw_fail::process()
+{
+ if (!_fsm.is_sending())
+ {
+ _sim.get_poller().remove_handler(_fsm);
+ _fsm.set_state(_st_failed);
+ }
+}
--- /dev/null
+#ifndef SCD_STSW_FAIL_H
+#define SCD_STSW_FAIL_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_fail : public scd_stsw_base
+{
+public:
+ scd_stsw_fail(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "fail"; }
+ virtual ~scd_stsw_fail() {}
+
+ /* scd_cont_fsm_if */
+ void set_fail();
+ void process();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_failed.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+void scd_stsw_failed::set_failed() {}
+
+
+void scd_stsw_failed::set_fail() {}
+
+
+bool scd_stsw_failed::active() const { return false; }
+
+
+bool scd_stsw_failed::failed() const { return true; }
--- /dev/null
+#ifndef SCD_STSW_FAILED_H
+#define SCD_STSW_FAILED_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_failed : public scd_stsw_base
+{
+public:
+ scd_stsw_failed(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "failed"; }
+ virtual ~scd_stsw_failed() {}
+
+ void set_failed();
+
+ /* scd_cont_fsm_if */
+ void set_fail();
+ bool active() const;
+ bool failed() const;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_idle.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_idle::send_time_req()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_REQ);
+ _fsm.send_command(cmd);
+ _fsm.save_state();
+ _fsm.set_state(_st_time_req);
+}
+
+
+bool scd_stsw_idle::idle() const { return true; }
+
+
+void scd_stsw_idle::set_busy()
+{
+ _fsm.set_state(_st_busy);
+}
+
+
+void scd_stsw_idle::set_done()
+{
+ scd_warn("slave " + _fsm.get_name() + " transition attempt from idle to done");
+}
--- /dev/null
+#ifndef SCD_STSW_IDLE_H
+#define SCD_STSW_IDLE_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_idle : public scd_stsw_base
+{
+public:
+ scd_stsw_idle(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "idle"; }
+ virtual ~scd_stsw_idle() {}
+
+ /* scd_cont_wrapper_if */
+ void send_time_req();
+ bool idle() const;
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_done();
+
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_init.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_init::set_connected()
+{
+ _sim.get_poller().register_handler(_fsm, SOCK_EV_READ | SOCK_EV_CLOSE);
+ _fsm.set_state(_st_busy);
+}
+
+
+void scd_stsw_init::set_failed()
+{
+ _fsm.set_state(_st_failed);
+}
+
+
+void scd_stsw_init::set_idle(const sc_core::sc_time& time)
+{
+ scd_error("init: illegal call to set_idle()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_init::set_busy()
+{
+ scd_error("init: illegal call to set_idle()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_init::set_done()
+{
+ scd_error("init: illegal call to set_done()");
+ throw scd_exception("illegal call");
+}
+
+
+void scd_stsw_init::set_fail()
+{
+ _fsm.set_state(_st_failed);
+}
+
+
+void scd_stsw_init::process() {}
+
+
+bool scd_stsw_init::active() const { return false; }
+
+
+bool scd_stsw_init::advance_time() const
+{
+ scd_error("illegal call to advance_time()");
+ throw scd_exception("illegal call");
+}
--- /dev/null
+#ifndef SCD_STSW_INIT_H
+#define SCD_STSW_INIT_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_init : public scd_stsw_base
+{
+public:
+ scd_stsw_init(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "init"; }
+ virtual ~scd_stsw_init() {}
+
+ void set_connected();
+ void set_failed();
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& time);
+ void set_busy();
+ void set_done();
+ void set_fail();
+ void process();
+ bool active() const;
+ bool advance_time() const;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_term_ack.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_term_ack::recv_term_nack()
+{
+ scd_warn("received term_nack message in wrong state");
+}
+
+
+void scd_stsw_term_ack::recv_term_ack()
+{
+ scd_warn("received term_nack message in wrong state");
+}
+
+
+void scd_stsw_term_ack::send_term_nack()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TERM_NACK);
+ _fsm.send_command(cmd);
+ _fsm.load_state();
+}
+
+
+void scd_stsw_term_ack::send_term()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TERM);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_terminate);
+}
+
+
+bool scd_stsw_term_ack::term_ack() const { return true; }
--- /dev/null
+#ifndef SCD_STSW_TERM_ACK_H
+#define SCD_STSW_TERM_ACK_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_term_ack : public scd_stsw_base
+{
+public:
+ scd_stsw_term_ack(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "term_ack"; }
+ virtual ~scd_stsw_term_ack() {}
+
+ /* scd_stsw_base */
+ void recv_term_nack();
+ void recv_term_ack();
+
+ /* scd_cont_wrapper_if */
+ void send_term_nack();
+ void send_term();
+ bool term_ack() const;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_term_req.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_term_req::recv_term_nack()
+{
+ _fsm.load_state();
+}
+
+
+void scd_stsw_term_req::recv_term_ack()
+{
+ _fsm.set_state(_st_term_ack);
+}
+
+
+void scd_stsw_term_req::send_term_nack()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TERM_NACK);
+ _fsm.send_command(cmd);
+ _fsm.load_state();
+}
+
+
+bool scd_stsw_term_req::term_req() const { return true; }
+
+
+void scd_stsw_term_req::set_busy()
+{
+ _time_step = sc_core::SC_ZERO_TIME;
+ _fsm.save_state(_st_busy);
+}
+
+
+void scd_stsw_term_req::set_idle(const sc_core::sc_time& time)
+{
+ _time_step = time;
+ _fsm.save_state(_st_idle);
+}
+
+
+void scd_stsw_term_req::set_done()
+{
+ _fsm.save_state(_st_done);
+}
--- /dev/null
+#ifndef SCD_STSW_TERM_REQ_H
+#define SCD_STSW_TERM_REQ_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_term_req : public scd_stsw_base
+{
+public:
+ scd_stsw_term_req(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "term_req"; }
+ virtual ~scd_stsw_term_req() {}
+
+ /* sdc_stsw_base */
+ void recv_term_nack();
+ void recv_term_ack();
+
+ /* scd_cont_wrapper_if */
+ void send_term_nack();
+ bool term_req() const;
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_idle(const sc_core::sc_time& time);
+ void set_done();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_terminate.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_terminate::set_fail() {}
+
+
+void scd_stsw_terminate::process()
+{
+ if (!_fsm.is_sending())
+ {
+ _sim.get_poller().remove_handler(_fsm);
+ _fsm.set_state(_st_terminated);
+ }
+}
--- /dev/null
+#ifndef SCD_STSW_TERMINATE_H
+#define SCD_STSW_TERMINATE_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_terminate : public scd_stsw_base
+{
+public:
+ scd_stsw_terminate(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "terminate"; }
+ virtual ~scd_stsw_terminate() {}
+
+ /* scd_cont_fsm_if */
+ void set_fail();
+ void process();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_terminated.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+void scd_stsw_terminated::set_failed() {}
+
+
+void scd_stsw_terminated::set_fail() {}
+
+
+bool scd_stsw_terminated::active() const { return false; }
--- /dev/null
+#ifndef SCD_STSW_TERMINATED_H
+#define SCD_STSW_TERMINATED_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_terminated : public scd_stsw_base
+{
+public:
+ scd_stsw_terminated(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "terminated"; }
+ virtual ~scd_stsw_terminated() {}
+
+ void set_failed();
+
+ /* scd_cont_fsm_if */
+ void set_fail();
+ bool active() const;
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_time_ack.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_time_ack::recv_time_nack()
+{
+ scd_warn("received time_nack message in wrong state");
+}
+
+
+void scd_stsw_time_ack::recv_time_ack()
+{
+ scd_warn("received time_nack message in wrong state");
+}
+
+
+void scd_stsw_time_ack::send_time_nack()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_NACK);
+ _fsm.send_command(cmd);
+ _fsm.load_state();
+}
+
+
+void scd_stsw_time_ack::send_time(const sc_core::sc_time& time)
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME, time);
+ _fsm.send_command(cmd);
+ _fsm.set_state(_st_busy);
+}
+
+
+bool scd_stsw_time_ack::time_ack() const { return true; }
+
+
+const sc_core::sc_time& scd_stsw_time_ack::get_time_step()
+{
+ return _time_step;
+}
--- /dev/null
+#ifndef SCD_STSW_TIME_ACK_H
+#define SCD_STSW_TIME_ACK_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_time_ack : public scd_stsw_base
+{
+public:
+ scd_stsw_time_ack(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "time_ack"; }
+ virtual ~scd_stsw_time_ack() {}
+
+ /* scd_stsw_base */
+ void recv_time_nack();
+ void recv_time_ack();
+
+ /* scd_cont_wrapper_if */
+ void send_time_nack();
+ void send_time(const sc_core::sc_time& time);
+ bool time_ack() const;
+ const sc_core::sc_time& get_time_step();
+};
+
+#endif
--- /dev/null
+#include "fsm/scd_stsw_time_req.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_cont_slave_wrapper.h"
+
+
+void scd_stsw_time_req::recv_time_nack()
+{
+ _fsm.load_state();
+}
+
+
+void scd_stsw_time_req::recv_time_ack()
+{
+ _fsm.set_state(_st_time_ack);
+}
+
+
+void scd_stsw_time_req::send_time_nack()
+{
+ scd_command* cmd = new scd_command(SCD_CM_CONTROL, SCD_CM_TIME_NACK);
+ _fsm.send_command(cmd);
+ _fsm.load_state();
+}
+
+
+bool scd_stsw_time_req::time_req() const { return true; }
+
+
+void scd_stsw_time_req::set_busy()
+{
+ _fsm.save_state(_st_busy);
+}
+
+
+void scd_stsw_time_req::set_idle(const sc_core::sc_time& time)
+{
+ _time_step = time;
+ _fsm.save_state(_st_idle);
+}
+
+
+void scd_stsw_time_req::set_done()
+{
+ _time_step = sc_core::SC_ZERO_TIME;
+ _fsm.save_state(_st_done);
+}
--- /dev/null
+#ifndef SCD_STSW_TIME_REQ_H
+#define SCD_STSW_TIME_REQ_H
+
+#include "fsm/scd_stsw_base.h"
+
+
+/* forward declaration */
+class scd_cont_slave_wrapper;
+
+
+class scd_stsw_time_req : public scd_stsw_base
+{
+public:
+ scd_stsw_time_req(scd_simulator& sim, scd_cont_slave_wrapper& fsm):
+ scd_stsw_base(sim, fsm) { _name = "time_req"; }
+ virtual ~scd_stsw_time_req() {}
+
+ /* sdc_stsw_base */
+ void recv_time_nack();
+ void recv_time_ack();
+
+ /* scd_cont_wrapper_if */
+ void send_time_nack();
+ bool time_req() const;
+
+ /* scd_cont_fsm_if */
+ void set_busy();
+ void set_idle(const sc_core::sc_time& time);
+ void set_done();
+
+};
+
+#endif
--- /dev/null
+#include "scd_chan_man.h"
+
+#include "scd_logging.h"
+
+
+scd_chan_man::scd_chan_man(scd_simulator &sim):
+ _sim(sim), _is_ready(false) {}
+
+
+scd_chan_man::~scd_chan_man()
+{
+ std::list<scd_out_connector*>::iterator coit;
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ for (coit = _connectors.begin(); coit != _connectors.end(); coit++)
+ delete *coit;
+
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ delete *chit;
+}
+
+
+void scd_chan_man::register_channel(const std::string &name, sc_prim_channel& mchan)
+{
+ if ( _get_channel(name) != NULL )
+ {
+ scd_warn("channel \"" + name + "\" already registered, ignoring...");
+ }
+ else
+ {
+ scd_chan_wrapper* wrap = new scd_chan_wrapper(_sim, name, mchan);
+ _channels.push_back(wrap);
+ }
+
+} // register_channel() - master
+
+
+void scd_chan_man::register_channel(const std::string &name,
+ sc_prim_channel& schan, const std::string &host, const uint16_t port)
+{
+ if ( _get_channel(name) != NULL )
+ {
+ scd_warn("channel \"" + name + "\" already registered, ignoring...");
+ }
+ else
+ {
+ // register channel
+ scd_chan_wrapper* wrap = new scd_chan_wrapper(_sim, name, schan);
+ _channels.push_back(wrap);
+
+ // create connector
+ scd_out_connector* conn = new scd_out_connector(_sim, SCD_CM_CHANNEL,
+ name);
+ conn->connect_to(host, port);
+ _connectors.push_back(conn);
+ }
+
+} // register_channel() - slave
+
+
+void scd_chan_man::init_process()
+{
+ if (_is_ready)
+ return;
+
+ std::list<scd_out_connector*>::iterator coit;
+
+ // check all connectors
+ for (coit = _connectors.begin(); coit != _connectors.end();)
+ {
+ scd_out_connector& conn = **coit;
+
+ // retry to connect if necessary
+ conn.process();
+
+ if (!conn.is_connecting() && !conn.has_connection())
+ {
+ // an error occured
+ scd_error("failed to connect channel \""
+ + conn.get_name() + "\"");
+
+ delete *coit;
+ coit = _connectors.erase(coit);
+
+ _sim.get_cont_man().set_fail();
+ return;
+ }
+ else if (!conn.is_connecting() && conn.has_connection())
+ {
+ // channel is connected
+ scd_chan_wrapper& chan = *_get_channel(conn.get_name());
+
+ if (chan.is_initialized())
+ {
+ scd_error("channel \""
+ + conn.get_name() + "\" already connected");
+
+ delete *coit;
+ coit = _connectors.erase(coit);
+
+ _sim.get_cont_man().set_fail();
+ return;
+ }
+ else
+ {
+ scd_info("connected channel \"" + conn.get_name() + "\"");
+ chan.connect(conn.get_connection());
+
+ delete *coit;
+ coit = _connectors.erase(coit);
+ }
+ } // end channel connected
+ else
+ {
+ // still trying to connect
+ coit++;
+ }
+ // end this connector
+ } // end check all connectors
+
+ // check if everything is initiated
+ _check_ready();
+
+} // init_process()
+
+
+void scd_chan_man::connect_channel(const scd_command &c, scd_socket* sock)
+{
+ std::string name = c.get_string();
+
+ scd_chan_wrapper* chan = _get_channel(name);
+
+ if (chan == NULL)
+ {
+ scd_warn("unknown channel \"" + name + "\" supplied by peer");
+ delete sock;
+ }
+ else if (chan->is_initialized())
+ {
+ scd_warn("channel \"" + name + "\" supplied by peer already connected");
+ }
+ else
+ {
+ scd_info("connected channel \"" + name + "\"");
+ chan->connect(sock);
+ }
+
+} // connect()
+
+
+bool scd_chan_man::ready() const { return _is_ready; }
+
+
+void scd_chan_man::process()
+{
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ (*chit)->process();
+
+} // process()
+
+
+void scd_chan_man::close()
+{
+ std::list<scd_out_connector*>::iterator coit;
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ for (coit = _connectors.begin(); coit != _connectors.end(); coit++)
+ (*coit)->close();
+
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ (*chit)->close();
+
+} // close()
+
+
+bool scd_chan_man::_check_ready()
+{
+ if (_is_ready)
+ return true;
+
+ if (_connectors.empty())
+ {
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ // check all channels
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ {
+ if ( !(*chit)->is_initialized() )
+ return false;
+ }
+
+ // all channels initiated
+ _is_ready = true;
+ return true;
+ }
+ else
+ return false;
+
+} // _check_ready()
+
+
+scd_chan_wrapper* scd_chan_man::_get_channel(const std::string& name)
+{
+ std::list<scd_chan_wrapper*>::iterator chit;
+
+ for (chit = _channels.begin(); chit != _channels.end(); chit++)
+ {
+ if ( (*chit)->get_name() == name )
+ return *chit;
+ }
+
+ return NULL;
+
+} // _get_channel()
--- /dev/null
+#ifndef SCD_CHAN_MAN_H
+#define SCD_CHAN_MAN_H
+
+#include <string>
+#include <list>
+
+#include <systemc>
+using sc_core::sc_prim_channel;
+
+#include "scd_simulator.h"
+#include "scd_command.h"
+#include "scd_chan_wrapper.h"
+#include "scd_out_connector.h"
+
+
+/* forward declaration */
+class scd_out_connector;
+class scd_chan_wrapper;
+
+
+/**
+ * The channel manager holds all remote channels. The channels have
+ * to be registered before the simulator is initiated. The channel
+ * manager will then initiate connections to other simulators
+ * and will handle channels from incomming connections.
+ * During simulation data is sent from the channel output buffers
+ * to remote hosts and data is received and stored in the input buffers.
+ * The channel implementation will then generate events to resume
+ * simulation processes.
+ */
+class scd_chan_man
+{
+public:
+ /**
+ * Constructor.
+ * \param sim the simulator
+ */
+ scd_chan_man(scd_simulator &sim);
+
+ virtual ~scd_chan_man();
+
+ /**
+ * Registers a remote channel with master endpoint on this host.
+ * Another host will initiate the connection and the channel will
+ * be connected by an in-connector calling connect_channel().
+ * \param name the name of the remote channel
+ * \param mchan the SystemC channel implementing the
+ * remote-in and/or the remote-out interface.
+ */
+ void register_channel(const std::string &name, sc_prim_channel& mchan);
+
+ /**
+ * Registers a remote channel with slave endpoint on this host.
+ * This host will initiate the connection to the host with the
+ * master endpoint. To drive this process init_process() has to
+ * be called periodically.
+ * \param name the name of the remote channel
+ * \param mchan the SystemC channel implementing the
+ * remote-in and/or the remote-out interface.
+ * \param host the FQDN or IP address of the remote simulator
+ * with the master endpoint of the channel
+ * \param port TCP port of the remote simulator
+ */
+ void register_channel(const std::string &name, sc_prim_channel& schan,
+ const std::string &host, const uint16_t port);
+ /**
+ * Drives the initialization process. Restarts outgoing connection
+ * attempts to connect channels to other simulators if previous
+ * attempts have timed out. ready() indicates the end of the
+ * initialization.
+ */
+ void init_process();
+
+ /**
+ * Connects a channel from an incomming connection. Is intended to be
+ * called from an in-connector.
+ * \param c the register command received by the in-connector (contains
+ * the channel name)
+ * \param sock the socket of the incoming connection that is used
+ * as the data channel
+ */
+ void connect_channel(const scd_command &c, scd_socket* sock);
+
+ /**
+ * Indicates if all clients have been connected.
+ * \return true if the channel manager completed initialization
+ */
+ bool ready() const;
+
+ /**
+ * Checks if channels have data in the output buffers and activates
+ * the transmission if necessary. Receiption is resumed if the input
+ * buffer can accept data again. Call this function after each
+ * simulation step (which might fill data into the buffers that has
+ * to be sent).
+ */
+ void process();
+
+ /**
+ * Closes all channels.
+ */
+ void close();
+
+private:
+ /* member variables */
+ scd_simulator& _sim;
+ std::list<scd_chan_wrapper*> _channels;
+ std::list<scd_out_connector*> _connectors;
+
+ bool _is_ready;
+
+ /* member functions */
+ bool _check_ready();
+ scd_chan_wrapper* _get_channel(const std::string& name);
+};
+
+#endif
--- /dev/null
+#include "scd_chan_wrapper.h"
+
+#include <cassert>
+#include <cstdio>
+
+#include "scd_logging.h"
+
+
+scd_chan_wrapper::scd_chan_wrapper(scd_simulator& sim, const std::string& name,
+ sc_prim_channel& chan):
+ _sim(sim), _name(name), _is_initialized(false),
+ _is_writing(false), _is_reading(false)
+{
+ try
+ {
+ _chan_in = &dynamic_cast<scd_rem_chan_in_if&>(chan);
+ } catch (std::bad_cast e)
+ {
+ _chan_in = NULL;
+ }
+
+ try
+ {
+ _chan_out = &dynamic_cast<scd_rem_chan_out_if&>(chan);
+ } catch (std::bad_cast e)
+ {
+ _chan_out = NULL;
+ }
+
+ if (_chan_in == NULL && _chan_out == NULL)
+ scd_warn("channel \"" + _name + "\" is not a remote channel");
+}
+
+
+scd_chan_wrapper::~scd_chan_wrapper()
+{
+ if ( _is_initialized )
+ {
+ _sim.get_poller().remove_handler(*this);
+ _socket->close();
+ delete _socket;
+ }
+}
+
+
+bool scd_chan_wrapper::is_initialized() const { return _is_initialized; }
+
+
+const std::string& scd_chan_wrapper::get_name() const { return _name; }
+
+
+void scd_chan_wrapper::connect(scd_socket* sock)
+{
+ assert(!_is_initialized);
+
+ _socket = sock;
+ _is_initialized = true;
+
+ sock_ev flags = SOCK_EV_CLOSE;
+ if (_chan_in != NULL)
+ {
+ flags |= SOCK_EV_READ;
+ _is_reading = true;
+ }
+ _sim.get_poller().register_handler(*this, flags);
+
+} // connect()
+
+
+void scd_chan_wrapper::process()
+{
+ // check if channel has data to send
+ if (_chan_out != NULL && _is_initialized )
+ {
+ if (!_is_writing && _socket->is_valid() && _chan_out->available() > 0 )
+ {
+ // register write event
+ sock_ev events;
+ _sim.get_poller().get_ev(*this, events);
+ events |= SOCK_EV_WRITE;
+ _sim.get_poller().set_ev( *this, events );
+ _is_writing = true;
+ }
+ }
+
+ // check if channel has data to read
+ if (_chan_in != NULL && _is_initialized )
+ {
+ if (!_is_reading && _socket->is_valid() && _chan_in->free() > 0 )
+ {
+ // register read event
+ sock_ev events;
+ _sim.get_poller().get_ev(*this, events);
+ events |= SOCK_EV_READ;
+ _sim.get_poller().set_ev( *this, events );
+ _is_reading = true;
+ }
+ }
+
+} // process()
+
+
+void scd_chan_wrapper::close()
+{
+ if (_is_initialized)
+ _socket->close();
+
+} // close()
+
+
+void scd_chan_wrapper::handle_sock_ev(sock_ev events)
+{
+ if (events & SOCK_EV_CLOSE)
+ {
+ scd_debug("channel \"" + _name + "\" closed connection");
+ _sim.get_poller().set_ev(*this, 0);
+ _sim.get_cont_man().set_fail();
+ close();
+ return;
+ } // end close event
+
+ if (events & SOCK_EV_READ)
+ {
+ _read_event();
+ }
+
+ if (events & SOCK_EV_WRITE)
+ {
+ _write_event();
+ }
+
+} // handle_sock_ev()
+
+
+const scd_socket& scd_chan_wrapper::get_sock() { return *_socket; }
+
+
+void scd_chan_wrapper::_read_event()
+{
+ size_t free = _chan_in->free();
+
+ /* receive portions as long as they can be received */
+ size_t recv = 0xFF; //dummy
+ while ( free != 0 && recv != 0)
+ {
+ free = ( free < SCD_CHAN_BUFLEN ) ? free : SCD_CHAN_BUFLEN ;
+ recv = _socket->recv(_buf, free);
+ if (recv != 0)
+ _chan_in->receive(_buf, recv);
+ free = _chan_in->free();
+ }
+
+ if (free == 0)
+ {
+ sock_ev events;
+ _sim.get_poller().get_ev(*this, events);
+ events &= ~SOCK_EV_READ;
+ _sim.get_poller().set_ev(*this, events );
+ _is_reading = false;
+ return;
+ }
+
+ if (!_socket->is_valid())
+ {
+ scd_debug("channel \"" + _name + "\" closed connection");
+ _sim.get_poller().set_ev(*this, 0);
+ _sim.get_cont_man().set_fail();
+ return;
+ }
+
+} // end _read_event()
+
+
+void scd_chan_wrapper::_write_event()
+{
+ /* send portions as long as they can be sent */
+ size_t sent = 0xFF; //dummy
+ while ( sent )
+ {
+ sent = _socket->send( _chan_out->send(), _chan_out->available() );
+ if (sent != 0)
+ _chan_out->remove(sent);
+ }
+
+ if (_chan_out->available() == 0)
+ {
+ sock_ev events;
+ _sim.get_poller().get_ev(*this, events);
+ events &= ~SOCK_EV_WRITE;
+ _sim.get_poller().set_ev(*this, events );
+ _is_writing = false;
+ return;
+ }
+
+ if (!_socket->is_valid())
+ {
+ scd_debug("channel \"" + _name + "\" closed connection");
+ _sim.get_poller().set_ev(*this, 0);
+ _sim.get_cont_man().set_fail();
+ }
+}
--- /dev/null
+#ifndef SCD_CHAN_WRAPPER_H
+#define SCD_CHAN_WRAPPER_H
+
+#include <string>
+
+#include <systemc>
+using sc_core::sc_prim_channel;
+
+#include "scd_sock_poller.h"
+#include "scd_socket.h"
+#include "scd_simulator.h"
+#include "scd_rem_chan_if.h"
+
+
+/**
+ * Size of the input buffer. Limits the ammount of data that
+ * can be read from the socket in one system call.
+ */
+static const size_t SCD_CHAN_BUFLEN = 512;
+
+/* forward declaration */
+class scd_simulator;
+
+
+/**
+ * Wrapper for a remote channel. Writes data from the output buffer
+ * of the channel to the socket. Receives data from the socket and
+ * writes it to the input buffer of the channel.
+ */
+class scd_chan_wrapper : public scd_sock_ev_handler_if
+{
+public:
+ /**
+ * Constructor.
+ * \param sim the simulation environment
+ * \param name the name of the channel
+ * \param chan the SystemC channel implementing
+ * remote channel interface(s)
+ */
+ scd_chan_wrapper(scd_simulator& sim, const std::string& name,
+ sc_prim_channel& chan);
+
+ virtual ~scd_chan_wrapper();
+
+ /**
+ * Indicates if a socket has been set for this channel.
+ * \return true if a socket has been set
+ */
+ bool is_initialized() const;
+
+ /**
+ * Returns the name of the channel.
+ */
+ const std::string& get_name() const;
+
+ /**
+ * Sets the socket of the channel.
+ */
+ void connect(scd_socket* sock);
+
+ /**
+ * Checks if data has to be send or can be received again and activates
+ * transmission if necessary. Call this function after every simulation
+ * step.
+ */
+ void process();
+
+ /**
+ * Closes the connection to the peer.
+ */
+ void close();
+
+
+ /* scd_sock_ev_handler_if */
+ void handle_sock_ev(sock_ev events);
+ const scd_socket &get_sock();
+
+private:
+ scd_simulator& _sim;
+ std::string _name;
+ bool _is_initialized;
+
+ scd_socket* _socket;
+ scd_rem_chan_in_if* _chan_in;
+ scd_rem_chan_out_if* _chan_out;
+ char _buf[SCD_CHAN_BUFLEN];
+ bool _is_writing;
+ bool _is_reading;
+
+ /* member functions */
+ void _write_event();
+ void _read_event();
+};
+
+#endif
--- /dev/null
+#include "scd_command.h"
+
+#include "cstring"
+#include "arpa/inet.h"
+
+
+scd_command::scd_command(): _type(0), _subtype(0), _msglen(0)
+{
+ _msg = NULL;
+}
+
+
+scd_command::scd_command(uint16_t type, uint16_t subtype):
+ _type(type), _subtype(subtype), _msglen(0)
+{
+ _msg = NULL;
+}
+
+
+scd_command::scd_command(uint16_t type, uint16_t subtype,
+ const std::string& msg):
+ _type(type), _subtype(subtype)
+{
+ if (msg.length() > 0)
+ {
+ _msglen = msg.length()+1;
+ _msg = new char[_msglen];
+ strncpy(_msg, msg.c_str(), _msglen);
+ _msg[_msglen-1] = 0;
+ }
+ else
+ {
+ _msglen = 0;
+ _msg = NULL;
+ }
+}
+
+
+scd_command::scd_command(uint16_t type, uint16_t subtype,
+ const sc_core::sc_time& time) : _type(type), _subtype(subtype)
+{
+ uint64_t value;
+ uint32_t hi, lo;
+
+ _msglen = 8;
+ _msg = new char[_msglen];
+
+ // obtain high and low words
+ value = time.value();
+ lo = value & 0xFFFFFFFF;
+ value >>= 32;
+ hi = value & 0xFFFFFFFF;
+
+ // do network conversion
+ hi = htonl(hi);
+ lo = htonl(lo);
+
+ // store to buffer
+ memcpy(_msg, &hi, 4);
+ memcpy(_msg + 4, &lo, 4);
+}
+
+
+
+scd_command::~scd_command()
+{
+ if (_msg != NULL)
+ delete _msg;
+}
+
+
+uint16_t scd_command::get_type() const { return _type; }
+
+
+uint16_t scd_command::get_subtype() const { return _subtype; }
+
+
+std::string scd_command::get_string() const
+{
+ if (_msglen <= 1)
+ return std::string();
+ else
+ return std::string(_msg, _msglen-1);
+}
+
+
+sc_core::sc_time scd_command::get_time() const
+{
+ if (_msglen != 8)
+ return sc_core::SC_ZERO_TIME;
+
+ uint64_t value;
+ uint32_t hi, lo;
+
+ // get value from buffer
+ memcpy(&hi, _msg, 4);
+ memcpy(&lo, _msg+4, 4);
+
+ // do network conversion
+ value = ntohl(hi);
+ value <<= 32;
+ value |= ntohl(lo);
+
+ return sc_core::sc_time(value, false);
+}
--- /dev/null
+#ifndef SCD_COMMAND_H
+#define SCD_COMMAND_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <string>
+
+#include "systemc"
+
+
+const size_t SCD_CM_MAXLEN = 512;
+const size_t SCD_CM_HEADER = 3*2;
+
+/* command types */
+const uint16_t SCD_CM_REGISTER = 1;
+const uint16_t SCD_CM_CONFIG = 2;
+const uint16_t SCD_CM_CONTROL = 3;
+
+/* command subtypes */
+// register
+const uint16_t SCD_CM_NETSIM = 1;
+const uint16_t SCD_CM_CHANNEL = 2;
+// control
+const uint16_t SCD_CM_BUSY = 1;
+const uint16_t SCD_CM_IDLE = 2;
+const uint16_t SCD_CM_DONE = 3;
+const uint16_t SCD_CM_FAILED = 4;
+const uint16_t SCD_CM_TIME_REQ = 5;
+const uint16_t SCD_CM_TIME_ACK = 6;
+const uint16_t SCD_CM_TIME_NACK = 7;
+const uint16_t SCD_CM_TIME = 8;
+const uint16_t SCD_CM_TERM_REQ = 9;
+const uint16_t SCD_CM_TERM_ACK = 10;
+const uint16_t SCD_CM_TERM_NACK = 11;
+const uint16_t SCD_CM_TERM = 12;
+
+/* forward declarations */
+class scd_command_reader;
+class scd_command_writer;
+
+
+/**
+ * Command class. Commands are control messages that are sent between
+ * the different simulators. A command has a type, a subtype and a potential
+ * message part.
+ */
+class scd_command
+{
+friend class scd_command_reader;
+friend class scd_command_writer;
+
+public:
+ /**
+ * Default constructor. Creates an empty command.
+ */
+ scd_command();
+
+ /*
+ * Constructor. Creates a command with no message part.
+ * \param type the type of this command
+ * \param subtype the subtype of this command
+ */
+ scd_command(uint16_t type, uint16_t subtype);
+
+ /**
+ * Constructor. Creates a new command with a string as message
+ * part.
+ */
+ scd_command(uint16_t type, uint16_t subtype, const std::string& msg);
+
+ /**
+ * Constructor. Creates a new command with a SystemC time value as
+ * message part.
+ */
+ scd_command(uint16_t type, uint16_t subtype, const sc_core::sc_time& time);
+
+ virtual ~scd_command();
+
+ /**
+ * Returns the type of the command.
+ */
+ uint16_t get_type() const;
+
+ /**
+ * Returns the subtype of the command.
+ */
+ uint16_t get_subtype() const;
+
+ /**
+ * Returns the message part interpreted as a string.
+ */
+ std::string get_string() const;
+
+ /**
+ * Returns the message part interpreted as a SystemC time.
+ * If the message part does not have the correct size SC_ZERO_TIME
+ * is returned instead.
+ */
+ sc_core::sc_time get_time() const;
+
+private:
+ uint16_t _type;
+ uint16_t _subtype;
+ uint16_t _msglen;
+ char* _msg;
+};
+
+#endif
--- /dev/null
+#include "scd_command_reader.h"
+
+#include <arpa/inet.h>
+
+#include "scd_logging.h"
+
+
+scd_command_reader::scd_command_reader():
+ _command(NULL), _is_reading(false), _success(false) {}
+
+
+scd_command_reader::~scd_command_reader()
+{
+ if (_is_reading || _success)
+ {
+ delete _command;
+ }
+}
+
+
+void scd_command_reader::set_socket(scd_socket& sock) { _socket = &sock; }
+
+
+void scd_command_reader::read()
+{
+ if (!_is_reading)
+ {
+ if (_success)
+ return;
+
+ _is_reading = true;
+ _header_read = false;
+ _remaining = SCD_CM_HEADER;
+ _off = 0;
+ _command = new scd_command;
+ }
+
+ // receive header
+ if (!_header_read)
+ {
+ // read header
+ size_t read = _socket->recv(_header_buf + _off, _remaining);
+ _remaining -= read;
+ _off += read;
+
+ if (_remaining == 0)
+ {
+ // read values from buffer
+ uint16_t* intbuf = reinterpret_cast<uint16_t*>(_header_buf);
+ _command->_type = ntohs( intbuf[0] );
+ _command->_subtype = ntohs( intbuf[1] );
+ _command->_msglen = ntohs( intbuf[2] );
+
+ _header_read = true;
+
+ // allocate buffer for further receiption
+ if (_command->_msglen > 0)
+ {
+ if (_command->_msglen > SCD_CM_MAXLEN)
+ {
+ // illegal command
+ _command->_msglen = 0;
+ delete _command;
+ _is_reading = false;
+ }
+ else
+ {
+ _command->_msg = new char[_command->_msglen];
+ _remaining = _command->_msglen;
+ _off = 0;
+ }
+ }
+ else
+ {
+ // command without payload
+ _command->_msglen = 0; // to prevent negative values
+ _remaining = 0;
+ _is_reading = false;
+ _success = true;
+ }
+ }
+ }
+
+ // receive msg
+ if (_header_read && _is_reading)
+ {
+ size_t read = _socket->recv(_command->_msg + _off, _remaining);
+ _remaining -= read;
+ _off += read;
+
+ if (_remaining == 0)
+ {
+ _is_reading = false;
+ _success = true;
+ }
+ }
+
+} // read()
+
+
+bool scd_command_reader::is_reading() { return _is_reading; }
+
+
+bool scd_command_reader::has_command() { return _success; }
+
+
+scd_command* scd_command_reader::get_command()
+{
+ if (!_success)
+ {
+ return NULL;
+ }
+ else
+ {
+ _success = false;
+ return _command;
+ }
+
+} // get_command()
--- /dev/null
+#ifndef SCD_COMMAND_READER_H
+#define SCD_COMMAND_READER_H
+
+#include "scd_command.h"
+#include "scd_socket.h"
+
+/**
+ * Reads commands from a socket. The receiption does not have to complete
+ * withing one call. As long as it is ongoing the socket shall not be read
+ * by the application.
+ */
+class scd_command_reader
+{
+public:
+ scd_command_reader();
+
+ virtual ~scd_command_reader();
+
+ /**
+ * Sets the socket to read from. Do not try to read before setting the
+ * socket.
+ */
+ void set_socket(scd_socket &sock);
+
+ /**
+ * Initiates reading a command if it is not reading yet or continues
+ * to read a previously unfinished command.
+ */
+ void read();
+
+ /**
+ * Indicates if a command is being read. This is the case between calling
+ * read() and the completion of the command (or failure if an illegal
+ * command was received).
+ * \return true if a command is currently being received
+ */
+ bool is_reading();
+
+ /**
+ * Indicates if a command has been received successfully and is ready
+ * to be picked up.
+ * \return true if a command can be collected
+ */
+ bool has_command();
+
+ /**
+ * Returns a successfully received command. The application has to free
+ * it by itself. The reader does not keep a reference.
+ * \return the command or NULL if has_command() is false
+ */
+ scd_command* get_command();
+
+private:
+ scd_socket* _socket;
+ scd_command* _command;
+ bool _is_reading;
+ bool _header_read;
+ bool _success;
+ size_t _remaining;
+ size_t _off;
+ char _header_buf[SCD_CM_HEADER];
+};
+
+#endif
--- /dev/null
+#include "scd_command_writer.h"
+
+#include <string.h>
+
+#include "scd_logging.h"
+
+
+scd_command_writer::scd_command_writer():
+ _is_writing(false), _remaining(0) {}
+
+
+scd_command_writer::~scd_command_writer()
+{
+ std::list<scd_command*>::iterator iter;
+ for ( iter = _commands.begin(); iter != _commands.end(); iter++)
+ delete *iter;
+}
+
+
+void scd_command_writer::set_socket(scd_socket& sock) { _socket = &sock; }
+
+
+bool scd_command_writer::is_writing() const { return _is_writing; }
+
+
+bool scd_command_writer::queue_command(scd_command* cmd)
+{
+ if (cmd->_msglen <= SCD_CM_MAXLEN)
+ {
+ _commands.push_back(cmd);
+ _is_writing = true;
+ return true;
+ }
+ else
+ {
+ scd_warn("command too long");
+ delete cmd;
+ return false;
+ }
+}
+
+void scd_command_writer::write()
+{
+ bool finishedmsg;
+ do
+ {
+ finishedmsg = _send_cmd();
+ }
+ while (finishedmsg);
+
+} // write()
+
+
+inline bool scd_command_writer::_send_cmd()
+{
+ if (!_is_writing)
+ return false;
+
+ if (_remaining == 0)
+ {
+ /* fetch next command */
+ scd_command* cmd = _commands.front();
+ _commands.pop_front();
+
+ // store header to buffer
+ uint16_t* intbuf = reinterpret_cast<uint16_t*>(_buf);
+ intbuf[0] = htons(cmd->_type);
+ intbuf[1] = htons(cmd->_subtype);
+ intbuf[2] = htons(cmd->_msglen);
+
+ // store message to buffer
+ memcpy(_buf + SCD_CM_HEADER, cmd->_msg, cmd->_msglen);
+
+ _remaining = SCD_CM_HEADER + cmd->_msglen;
+ _off = 0;
+ delete cmd;
+ }
+
+ size_t sent = _socket->send(_buf + _off, _remaining);
+
+ _off += sent;
+ _remaining -= sent;
+
+ if (_remaining == 0)
+ {
+ if (_commands.empty())
+ _is_writing = false;
+ return true;
+ }
+ else
+ return false;
+
+} // _send_cmd()
--- /dev/null
+#ifndef SCD_COMMAND_WRITER_H
+#define SCD_COMMAND_WRITER_H
+
+#include <list>
+
+#include "scd_command.h"
+#include "scd_socket.h"
+
+
+/**
+ * Queues multiple commands and writes then to a socket continuously.
+ */
+class scd_command_writer
+{
+public:
+ scd_command_writer();
+
+ virtual ~scd_command_writer();
+
+ /**
+ * Sets the socket to write to. Do not try to write before
+ * setting the socket.
+ */
+ void set_socket(scd_socket& sock);
+
+ /**
+ * Indicates if the writer is currently sending a command.
+ * \return true if the writer is busy sending commands
+ */
+ bool is_writing() const;
+
+ /**
+ * Queues a command to be sent. Commands will be sent out in FIFO
+ * manner. Sending is not initiated by this call.
+ * \param message to send
+ * \return false if the message is longet than SCD_CM_MAXLEN. In this
+ * case the message is destroyed.
+ */
+ bool queue_command(scd_command* cmd);
+
+ /**
+ * Write commands or part of commands to the socket. As many queued
+ * commands as possible are sent but none has to be finished.
+ * \exception scd_exception if unexpected errors occured
+ */
+ void write();
+
+private:
+ scd_socket* _socket;
+ bool _is_writing;
+
+ std::list<scd_command*>_commands;
+ char _buf[SCD_CM_HEADER + SCD_CM_MAXLEN];
+ size_t _remaining;
+ size_t _off;
+
+ inline bool _send_cmd();
+
+};
+
+#endif
--- /dev/null
+#ifndef SCD_CONT_MAN_H
+#define SCD_CONT_MAN_H
+
+#include <string>
+
+#include "fsm/scd_cont_fsm_if.h"
+
+
+const bool SCD_MASTER = true;
+const bool SCD_SLAVE = false;
+
+const int SCD_CONT_DELAY = 20;
+
+/**
+ * Control manager. Shall be set up before the simulation is initialized.
+ */
+class scd_cont_man : public scd_cont_fsm_if
+{
+public:
+ virtual ~scd_cont_man() {};
+
+ /**
+ * Sets the master simulator for a slave.
+ * \param host the FQDN or IP of the master simulator
+ * \param port the TCP port of the master simulator
+ * \exception scd_exception if the simulator is not a slave
+ */
+ virtual void set_master(const std::string& host, uint16_t port) = 0;
+
+ /**
+ * Registers a slave simulator for the master.
+ * \param name the name of the slave
+ * \exception scd_exception if the simulator is not the master
+ */
+ virtual void register_slave(const std::string& name) = 0;
+};
+
+#endif
--- /dev/null
+#include "scd_cont_man_master.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+scd_cont_man_master::scd_cont_man_master(scd_simulator& sim):
+ _sim(sim), scd_cont_fsm("master"),
+ _st_init(sim, *this), _st_busy(sim, *this), _st_idle(sim, *this),
+ _st_done(sim, *this), _st_time_req(sim, *this), _st_time(sim, *this),
+ _st_term_req(sim, *this), _st_terminate(sim, *this),
+ _st_terminated(sim, *this), _st_fail(sim, *this), _st_failed(sim, *this)
+{
+ // set initial state
+ set_state(_st_init);
+}
+
+
+scd_cont_man_master::~scd_cont_man_master()
+{
+ std::list<scd_cont_slave_wrapper*>::iterator it;
+
+ for (it = _slaves.begin(); it != _slaves.end(); it++)
+ delete *it;
+}
+
+
+void scd_cont_man_master::connect_slave(const scd_command &c, scd_socket* sock)
+{
+ std::string name = c.get_string();
+
+ scd_cont_slave_wrapper* slave = _get_slave(name);
+
+ if (slave == NULL)
+ {
+ scd_warn("unknown slave \"" + name + "\"");
+ delete sock;
+ }
+ else
+ slave->connect(sock);
+
+} // connect()
+
+
+void scd_cont_man_master::set_master(const std::string& host, uint16_t port)
+{
+ scd_error("simulator is master, can not have another master");
+ throw scd_exception("simulator is master");
+} // set_master()
+
+
+void scd_cont_man_master::register_slave(const std::string& name)
+{
+ if ( _get_slave(name) != NULL )
+ {
+ scd_warn("slave \"" + name + "\" already registered, ignoring...");
+ }
+ else
+ {
+ scd_cont_slave_wrapper* wrap;
+ wrap = new scd_cont_slave_wrapper(_sim, name);
+ _slaves.push_back(wrap);
+ }
+
+} // register_slave
+
+
+void scd_cont_man_master::process()
+{
+ std::list<scd_cont_slave_wrapper*>::iterator it;
+
+ // process all slaves
+ for (it = _slaves.begin(); it != _slaves.end(); it++)
+ (*it)->process();
+
+ // process the local state
+ _state->process();
+}
+
+
+scd_cont_slave_wrapper* scd_cont_man_master::_get_slave(const std::string& name)
+{
+ std::list<scd_cont_slave_wrapper*>::iterator it;
+
+ for (it = _slaves.begin(); it != _slaves.end(); it++)
+ {
+ if ( (*it)->get_name() == name )
+ return *it;
+ }
+
+ return NULL;
+
+} // _get_slave()
--- /dev/null
+#ifndef SCD_CONT_MAN_MASTER_H
+#define SCD_CONT_MAN_MASTER_H
+
+#include <list>
+
+#include "scd_simulator.h"
+#include "scd_cont_man.h"
+#include "scd_cont_slave_wrapper.h"
+#include "fsm/scd_cont_fsm.h"
+
+#include "fsm/scd_stm_init.h"
+#include "fsm/scd_stm_busy.h"
+#include "fsm/scd_stm_idle.h"
+#include "fsm/scd_stm_done.h"
+#include "fsm/scd_stm_time_req.h"
+#include "fsm/scd_stm_time.h"
+#include "fsm/scd_stm_term_req.h"
+#include "fsm/scd_stm_terminate.h"
+#include "fsm/scd_stm_terminated.h"
+#include "fsm/scd_stm_fail.h"
+#include "fsm/scd_stm_failed.h"
+
+/**
+ * Control manager for the master. Waits for all slaves to connect.
+ * Synchronizes the global simulation state.
+ */
+class scd_cont_man_master : public scd_cont_man, public scd_cont_fsm
+{
+ friend class scd_stm_base;
+
+public:
+ /**
+ * Constructor.
+ * \param sim the simulation environment
+ */
+ scd_cont_man_master(scd_simulator& sim);
+
+ virtual ~scd_cont_man_master();
+
+ /**
+ * Connects a slave. Is called from an in-connector.
+ * \param c the register command that has been received by the in-connector
+ * (contains the slave name).
+ * \param sock the incomming connection
+ */
+ void connect_slave(const scd_command& c, scd_socket* sock);
+
+ /* scd_cont_man */
+ void set_master(const std::string& host, uint16_t port);
+ void register_slave(const std::string& name);
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& t) { return _state->set_idle(t); }
+ void set_busy() { return _state->set_busy(); }
+ void set_done() { return _state->set_done(); }
+ void set_fail() { return _state->set_fail(); }
+ void process();
+ bool active() const { return _state->active(); }
+ bool busy() const { return _state->busy(); }
+ bool failed() const { return _state->failed(); }
+ bool advance_time() const { return _state->advance_time(); }
+ const sc_core::sc_time& get_time_step() { return _state->get_time_step(); }
+
+private:
+ scd_simulator& _sim;
+ std::list<scd_cont_slave_wrapper*> _slaves;
+ sc_core::sc_time _time_step;
+
+ /* states */
+ scd_stm_init _st_init;
+ scd_stm_busy _st_busy;
+ scd_stm_idle _st_idle;
+ scd_stm_done _st_done;
+ scd_stm_time_req _st_time_req;
+ scd_stm_time _st_time;
+ scd_stm_term_req _st_term_req;
+ scd_stm_terminate _st_terminate;
+ scd_stm_terminated _st_terminated;
+ scd_stm_fail _st_fail;
+ scd_stm_failed _st_failed;
+
+ /* member functions */
+ scd_cont_slave_wrapper* _get_slave(const std::string& name);
+};
+
+#endif
--- /dev/null
+#include "scd_cont_man_slave.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+scd_cont_man_slave::scd_cont_man_slave(scd_simulator& sim):
+ scd_cont_fsm("slave"), _sim(sim),
+ _connector(sim, SCD_CM_NETSIM, sim.get_name()), _has_master(false),
+ _st_init(sim, *this), _st_busy(sim, *this), _st_fail(sim, *this),
+ _st_failed(sim, *this), _st_idle(sim, *this), _st_done(sim, *this),
+ _st_time_ack(sim, *this), _st_time(sim, *this), _st_term_ack(sim, *this),
+ _st_terminated(sim, *this)
+{
+ // set initial state
+ set_state(_st_init);
+}
+
+
+scd_cont_man_slave::~scd_cont_man_slave()
+{
+ if (_socket != NULL)
+ delete _socket;
+}
+
+
+void scd_cont_man_slave::set_socket()
+{
+ _socket = _connector.get_connection();
+ _writer.set_socket(*_socket);
+ _reader.set_socket(*_socket);
+} // set_socket()
+
+
+void scd_cont_man_slave::send_command(scd_command* cmd)
+{
+ // register write event if not registered
+ if (!_writer.is_writing() && _socket->is_valid())
+ _sim.get_poller().set_ev(*this, SOCK_EV_WRITE | SOCK_EV_READ
+ | SOCK_EV_CLOSE);
+
+ // queue command to be written
+ _writer.queue_command(cmd);
+}
+
+
+bool scd_cont_man_slave::is_sending()
+{
+ return _writer.is_writing() && _socket->is_valid();
+}
+
+
+void scd_cont_man_slave::close()
+{
+ if (_socket != NULL)
+ _socket->close();
+}
+
+
+void scd_cont_man_slave::set_master(const std::string& host, uint16_t port)
+{
+ if (!_has_master)
+ _connector.connect_to(host, port);
+ else
+ {
+ scd_error("master already set");
+ throw scd_exception("master already set");
+ }
+} // set_master()
+
+
+void scd_cont_man_slave::register_slave(const std::string& name)
+{
+ scd_error("simulator is slave, can not have other slaves");
+ throw scd_exception("simulator is slave");
+
+} // register_slave
+
+
+void scd_cont_man_slave::handle_sock_ev(sock_ev events)
+{
+ scd_sts_base& state = *static_cast<scd_sts_base*>(_state);
+
+ if (events & SOCK_EV_CLOSE)
+ {
+ scd_error("connection to master lost");
+ _socket->close();
+ state.set_failed();
+ return;
+ }
+
+ if (events & SOCK_EV_READ)
+ {
+ _reader.read();
+
+ if (!_socket->is_valid())
+ {
+ // connection closed
+ scd_error("connection to master lost");
+ state.set_failed();
+ return;
+ }
+
+ if (!_reader.is_reading() && !_reader.has_command())
+ {
+ // received an illegal command
+ scd_error("received illegal command");
+ state.set_fail();
+ return;
+ }
+
+ if (_reader.has_command())
+ {
+ scd_command* cmd = _reader.get_command();
+ _process_cmd(*cmd);
+ delete cmd;
+ }
+
+ } // end read event
+
+ if (events & SOCK_EV_WRITE)
+ {
+ _writer.write();
+ if (!_writer.is_writing())
+ {
+ // done sending commands
+ _sim.get_poller().set_ev(*this, SOCK_EV_READ | SOCK_EV_CLOSE);
+ }
+ } // end write event
+
+ if (!_socket->is_valid())
+ {
+ scd_error("connection to master lost");
+ state.set_failed();
+ }
+
+} // handle_sock_ev()
+
+
+const scd_socket& scd_cont_man_slave::get_sock() { return *_socket; }
+
+
+void scd_cont_man_slave::_process_cmd(scd_command& cmd)
+{
+ if (cmd.get_type() != SCD_CM_CONTROL)
+ {
+ scd_warn("received non-control command");
+ return;
+ }
+
+ scd_sts_base* state = static_cast<scd_sts_base*>(_state);
+
+ switch (cmd.get_subtype())
+ {
+ case SCD_CM_FAILED:
+ scd_error("master failed");
+ state->set_failed();
+ break;
+ case SCD_CM_TIME_REQ:
+ state->recv_time_req();
+ break;
+ case SCD_CM_TIME_NACK:
+ state->recv_time_nack();
+ break;
+ case SCD_CM_TIME:
+ state->recv_time(cmd.get_time());
+ break;
+ case SCD_CM_TERM_REQ:
+ state->recv_term_req();
+ break;
+ case SCD_CM_TERM_NACK:
+ state->recv_term_nack();
+ break;
+ case SCD_CM_TERM:
+ state->recv_term();
+ break;
+ default:
+ scd_warn("received unknown command");
+ break;
+ }
+} // _process_cmd()
--- /dev/null
+#ifndef SCD_CONT_MAN_SLAVE_H
+#define SCD_CONT_MAN_SLAVE_H
+
+#include "scd_simulator.h"
+#include "scd_socket.h"
+#include "scd_out_connector.h"
+#include "scd_command_writer.h"
+#include "scd_command_reader.h"
+#include "scd_cont_man.h"
+#include "scd_sock_poller.h"
+
+#include "fsm/scd_cont_fsm.h"
+#include "fsm/scd_sts_init.h"
+#include "fsm/scd_sts_busy.h"
+#include "fsm/scd_sts_idle.h"
+#include "fsm/scd_sts_done.h"
+#include "fsm/scd_sts_time_ack.h"
+#include "fsm/scd_sts_time.h"
+#include "fsm/scd_sts_term_ack.h"
+#include "fsm/scd_sts_terminated.h"
+#include "fsm/scd_sts_fail.h"
+#include "fsm/scd_sts_failed.h"
+
+/**
+ * Control manager for a slave. Connects to the master controller and
+ * synchronizes the local and global simulation state.
+ */
+class scd_cont_man_slave : public scd_cont_man, public scd_cont_fsm,
+ public scd_sock_ev_handler_if
+{
+ friend class scd_sts_base;
+
+public:
+ /**
+ * Constructor.
+ * \param sim the simulation environment
+ */
+ scd_cont_man_slave(scd_simulator& sim);
+
+ virtual ~scd_cont_man_slave();
+
+ /**
+ * Sets the socket where to read from and write to after the connection
+ * has been established to the master.
+ */
+ void set_socket();
+
+ /**
+ * Sends a command to the master.
+ * \param cmd the command to send
+ */
+ void send_command(scd_command* cmd);
+
+ /**
+ * Indicates if a command is being sent to the master (and did not finish
+ * yet).
+ * \return true if a command is currently being sent
+ */
+ bool is_sending();
+
+ /**
+ * Closes the connection to the master controller.
+ */
+ void close();
+
+ /* scd_cont_man */
+ void set_master(const std::string& host, uint16_t port);
+ void register_slave(const std::string& name);
+
+ /* scd_cont_fsm_if */
+ void set_idle(const sc_core::sc_time& t) { return _state->set_idle(t); }
+ void set_busy() { return _state->set_busy(); }
+ void set_done() { return _state->set_done(); }
+ void set_fail() { return _state->set_fail(); }
+ void process() { return _state->process(); }
+ bool active() const { return _state->active(); }
+ bool busy() const { return _state->busy(); }
+ bool failed() const { return _state->failed(); }
+ bool advance_time() const { return _state->advance_time(); }
+ const sc_core::sc_time& get_time_step() { return _state->get_time_step(); }
+
+ /* scd_sock_ev_handler_if */
+ void handle_sock_ev(sock_ev events);
+ const scd_socket& get_sock();
+
+private:
+ scd_simulator& _sim;
+
+ scd_socket* _socket;
+ scd_out_connector _connector;
+ scd_command_writer _writer;
+ scd_command_reader _reader;
+ bool _has_master;
+
+ /* states */
+ scd_sts_init _st_init;
+ scd_sts_busy _st_busy;
+ scd_sts_idle _st_idle;
+ scd_sts_done _st_done;
+ scd_sts_time_ack _st_time_ack;
+ scd_sts_time _st_time;
+ scd_sts_term_ack _st_term_ack;
+ scd_sts_terminated _st_terminated;
+ scd_sts_fail _st_fail;
+ scd_sts_failed _st_failed;
+
+ /* member functions */
+ void _process_cmd(scd_command& cmd);
+};
+
+#endif
--- /dev/null
+#include "scd_cont_slave_wrapper.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+
+scd_cont_slave_wrapper::scd_cont_slave_wrapper(scd_simulator& sim,
+ const std::string& name):
+ _sim(sim), scd_cont_fsm(name), _name(name), _is_connected(false),
+ _st_init(sim, *this), _st_busy(sim, *this), _st_idle(sim, *this),
+ _st_done(sim, *this), _st_time_req(sim, *this), _st_time_ack(sim, *this),
+ _st_term_req(sim, *this), _st_term_ack(sim, *this),
+ _st_terminate(sim, *this), _st_terminated(sim, *this), _st_fail(sim, *this),
+ _st_failed(sim, *this)
+{
+ // set initial state
+ set_state(_st_init);
+}
+
+
+scd_cont_slave_wrapper::~scd_cont_slave_wrapper()
+{
+ if (_socket != NULL)
+ delete _socket;
+}
+
+
+const std::string& scd_cont_slave_wrapper::get_name() const { return _name; }
+
+
+void scd_cont_slave_wrapper::connect(scd_socket* sock)
+{
+ if (!_is_connected)
+ {
+ _socket = sock;
+ _writer.set_socket(*_socket);
+ _reader.set_socket(*_socket);
+ _is_connected = true;
+ scd_info("slave \"" + _name + "\" connected");
+ static_cast<scd_stsw_base*>(_state)->set_connected();
+ }
+ else
+ {
+ scd_warn("slave " + _name + " has already been connected");
+ delete sock;
+ }
+} // connect()
+
+
+void scd_cont_slave_wrapper::send_command(scd_command* cmd)
+{
+ // register write event if not registered
+ if (!_writer.is_writing() && _is_connected && _socket->is_valid())
+ _sim.get_poller().set_ev(*this, SOCK_EV_WRITE | SOCK_EV_READ
+ | SOCK_EV_CLOSE);
+
+ // queue command to be written
+ _writer.queue_command(cmd);
+}
+
+
+bool scd_cont_slave_wrapper::is_sending() const
+{
+ return _writer.is_writing() && _is_connected && _socket->is_valid();
+}
+
+
+void scd_cont_slave_wrapper::close()
+{
+ if (_is_connected)
+ _socket->close();
+}
+
+
+void scd_cont_slave_wrapper::handle_sock_ev(sock_ev events)
+{
+ scd_stsw_base& state = *static_cast<scd_stsw_base*>(_state);
+
+ if (events & SOCK_EV_CLOSE)
+ {
+ _socket->close();
+ scd_error("connection to slave \"" + _name + "\" lost");
+ state.set_failed();
+ return;
+ }
+
+ if (events & SOCK_EV_READ)
+ {
+ _reader.read();
+
+ if (!_socket->is_valid())
+ {
+ // connection closed
+ scd_error("connection to slave \"" + _name + "\" lost");
+ state.set_failed();
+ return;
+ }
+
+ if (!_reader.is_reading() && !_reader.has_command())
+ {
+ // received an illegal command
+ scd_error("received illegal command");
+ state.set_fail();
+ return;
+ }
+
+ if (_reader.has_command())
+ {
+ scd_command* cmd = _reader.get_command();
+ _process_cmd(*cmd);
+ delete cmd;
+ }
+
+ } // end read event
+
+ if (events & SOCK_EV_WRITE)
+ {
+ _writer.write();
+
+ if (!_writer.is_writing())
+ {
+ // done sending commands
+ _sim.get_poller().set_ev(*this, SOCK_EV_READ | SOCK_EV_CLOSE);
+ }
+
+ if (!_socket->is_valid())
+ {
+ scd_error("connection to slave \"" + _name + "\" lost");
+ state.set_failed();
+ return;
+ }
+ } // end write event
+
+
+} // handle_sock_ev()
+
+
+const scd_socket& scd_cont_slave_wrapper::get_sock() { return *_socket; }
+
+
+void scd_cont_slave_wrapper::_process_cmd(const scd_command& cmd)
+{
+ if (cmd.get_type() != SCD_CM_CONTROL)
+ {
+ scd_warn("received non-control command");
+ return;
+ }
+
+ scd_stsw_base* state = static_cast<scd_stsw_base*>(_state);
+
+ switch(cmd.get_subtype())
+ {
+ case SCD_CM_BUSY:
+ state->set_busy();
+ break;
+ case SCD_CM_IDLE:
+ state->set_idle(cmd.get_time());
+ break;
+ case SCD_CM_DONE:
+ state->set_done();
+ break;
+ case SCD_CM_TIME_NACK:
+ state->recv_time_nack();
+ break;
+ case SCD_CM_TIME_ACK:
+ state->recv_time_ack();
+ break;
+ case SCD_CM_TERM_NACK:
+ state->recv_term_nack();
+ break;
+ case SCD_CM_TERM_ACK:
+ state->recv_term_ack();
+ break;
+ case SCD_CM_FAILED:
+ scd_error("slave \"" + _name + "\" failed");
+ state->set_failed();
+ break;
+ default:
+ scd_warn("received unknown command");
+ break;
+ }
+} // _process_cmd()
--- /dev/null
+#ifndef SCD_CONT_SLAVE_WRAPPER_H
+#define SCD_CONT_SLAVE_WRAPPER_H
+
+#include "scd_simulator.h"
+#include "scd_socket.h"
+#include "scd_command_writer.h"
+#include "scd_command_reader.h"
+#include "scd_cont_man.h"
+#include "scd_sock_poller.h"
+#include "fsm/scd_cont_fsm.h"
+#include "fsm/scd_cont_wrapper_if.h"
+
+#include "fsm/scd_stsw_init.h"
+#include "fsm/scd_stsw_busy.h"
+#include "fsm/scd_stsw_idle.h"
+#include "fsm/scd_stsw_done.h"
+#include "fsm/scd_stsw_time_req.h"
+#include "fsm/scd_stsw_time_ack.h"
+#include "fsm/scd_stsw_term_req.h"
+#include "fsm/scd_stsw_term_ack.h"
+#include "fsm/scd_stsw_terminate.h"
+#include "fsm/scd_stsw_terminated.h"
+#include "fsm/scd_stsw_fail.h"
+#include "fsm/scd_stsw_failed.h"
+
+/**
+ * Control manager wrapper for a slave. Reflects the masters view of the
+ * slaves state.
+ */
+class scd_cont_slave_wrapper : public scd_cont_fsm_if, public scd_cont_fsm,
+ public scd_cont_wrapper_if, public scd_sock_ev_handler_if
+{
+ friend class scd_stsw_base;
+
+public:
+ /**
+ * Constructor.
+ * \param sim the simulation environment
+ * \param name the name of the slave
+ */
+ scd_cont_slave_wrapper(scd_simulator& sim, const std::string& name);
+
+ virtual ~scd_cont_slave_wrapper();
+
+ /**
+ * Returns the name of the slave.
+ */
+ const std::string& get_name() const;
+
+ /**
+ * Sets the socket of the slave.
+ * \param sock the connection to the slave
+ */
+ void connect(scd_socket* sock);
+
+ /**
+ * Sends a command to the slave.
+ */
+ void send_command(scd_command* cmd);
+
+ /**
+ * Indicates if a command is being sent to the slave.
+ * \return true if a command is still being sent
+ */
+ bool is_sending() const;
+
+ /**
+ * Closes the connection to the slave.
+ */
+ void close();
+
+ /* scd_cont_slave_wrapper_if */
+ void send_time_req()
+ { return static_cast<scd_stsw_base*>(_state)->send_time_req(); }
+ void send_time_nack()
+ { return static_cast<scd_stsw_base*>(_state)->send_time_nack(); }
+ void send_time(const sc_core::sc_time& time)
+ { return static_cast<scd_stsw_base*>(_state)->send_time(time); }
+ void send_term_req()
+ { return static_cast<scd_stsw_base*>(_state)->send_term_req(); }
+ void send_term_nack()
+ { return static_cast<scd_stsw_base*>(_state)->send_term_nack(); }
+ void send_term()
+ { return static_cast<scd_stsw_base*>(_state)->send_term(); }
+ bool time_req() const
+ { return static_cast<scd_stsw_base*>(_state)->time_req(); }
+ bool time_ack() const
+ { return static_cast<scd_stsw_base*>(_state)->time_ack(); }
+ bool term_req() const
+ { return static_cast<scd_stsw_base*>(_state)->term_req(); }
+ bool term_ack() const
+ { return static_cast<scd_stsw_base*>(_state)->term_ack(); }
+ bool idle() const
+ { return static_cast<scd_stsw_base*>(_state)->idle(); }
+ bool done() const
+ { return static_cast<scd_stsw_base*>(_state)->done(); }
+
+ /* scd_cont_fsm_if */
+ void set_busy() { return _state->set_busy(); }
+ void set_idle(const sc_core::sc_time& t) { return _state->set_idle(t); }
+ void set_done() { return _state->set_done(); }
+ void set_fail() { return _state->set_fail(); }
+ void process() { return _state->process(); }
+ bool active() const { return _state->active(); }
+ bool busy() const { return _state->busy(); }
+ bool failed() const { return _state->failed(); }
+ bool advance_time() const { return _state->advance_time(); }
+ const sc_core::sc_time& get_time_step() { return _state->get_time_step(); }
+
+ /* scd_sock_ev_handler_if */
+ void handle_sock_ev(sock_ev events);
+ const scd_socket& get_sock();
+
+private:
+ scd_simulator& _sim;
+ std::string _name;
+ bool _is_connected;
+
+ scd_socket* _socket;
+ scd_command_writer _writer;
+ scd_command_reader _reader;
+ sc_core::sc_time _time_step;
+
+ /* states */
+ scd_stsw_init _st_init;
+ scd_stsw_busy _st_busy;
+ scd_stsw_idle _st_idle;
+ scd_stsw_done _st_done;
+ scd_stsw_time_req _st_time_req;
+ scd_stsw_time_ack _st_time_ack;
+ scd_stsw_term_req _st_term_req;
+ scd_stsw_term_ack _st_term_ack;
+ scd_stsw_terminate _st_terminate;
+ scd_stsw_terminated _st_terminated;
+ scd_stsw_fail _st_fail;
+ scd_stsw_failed _st_failed;
+
+ /* member functions */
+ void _process_cmd(const scd_command& cmd);
+};
+
+#endif
--- /dev/null
+#include "scd_exception.h"
+
+
+scd_exception::scd_exception(const std::string& msg): _msg(msg)
+{
+ _get_backtrace();
+}
+
+
+scd_exception::scd_exception(const std::string& msg, int errn)
+{
+ _msg = msg + ": " + std::string(strerror(errn));
+ _get_backtrace();
+}
+
+
+const char* scd_exception::what() throw() { return _msg.c_str(); }
+
+
+const char* scd_exception::stacktrace() { return _backtrace.c_str(); }
+
+
+void scd_exception::_get_backtrace()
+{
+ void* traces[SCD_EX_TRACES];
+ int num_traces = backtrace(traces, SCD_EX_TRACES);
+ char ** symbols = backtrace_symbols(traces, num_traces);
+ for (int i = 0; i < num_traces; i++)
+ {
+ _backtrace += std::string(symbols[i]);
+ _backtrace += "\r\n";
+ }
+
+ free(symbols);
+} // _obtain_backtrace()
--- /dev/null
+#ifndef SCD_EXCEPTION_H
+#define SCD_EXCEPTION_H
+
+#include <string>
+#include <exception>
+#include <execinfo.h>
+
+
+/**
+ * Maximum level of stacktrace.
+ */
+const int SCD_EX_TRACES = 15;
+
+
+/**
+ * General exeption. Can give a stack trace and generates error messages
+ * from error numbers.
+ */
+class scd_exception : public std::exception
+{
+public:
+ /**
+ * Constructor to create an exception with a string as cause.
+ * \param the cause
+ */
+ scd_exception(const std::string& msg);
+
+ /**
+ * Constroctor to create an exception with a string and an error
+ * message generated from an error number (errno) as cause.
+ * \param the cause prefix
+ * \param the error number to generate the error message for
+ */
+ scd_exception(const std::string& msg, int errn);
+
+ virtual ~scd_exception() throw() {}
+
+ /**
+ * Returns a C-String showing the cause of the exception.
+ */
+ virtual const char* what() throw();
+
+ /**
+ * Returns a C-String showing the stack trace. For name resolution
+ * -rdynamic has to be used while compiling.
+ */
+ const char* stacktrace();
+
+private:
+ std::string _msg;
+ std::string _backtrace;
+
+ void _get_backtrace();
+
+};
+
+#endif
--- /dev/null
+#include "scd_in_connector.h"
+
+#include "scd_logging.h"
+#include "scd_cont_man_master.h"
+
+
+scd_in_connector::scd_in_connector(scd_simulator &sim, scd_socket* sock):
+ _sim(sim), _socket(sock), _is_connecting(true)
+{
+ // register this event handler
+ _sim.get_poller().register_handler(*this, SOCK_EV_READ | SOCK_EV_CLOSE);
+
+ // set the socket for the reader
+ _reader.set_socket(*sock);
+}
+
+
+scd_in_connector::~scd_in_connector()
+{
+ if (_is_connecting)
+ {
+ _cleanup();
+ }
+}
+
+
+bool scd_in_connector::is_connecting() { return _is_connecting; }
+
+
+void scd_in_connector::handle_sock_ev(sock_ev events)
+{
+ if (events & SOCK_EV_CLOSE)
+ {
+ scd_debug("in_connector: received close event");
+ _cleanup();
+ }
+ else if (events & SOCK_EV_READ)
+ {
+ _reader.read();
+
+ if (!_socket->is_valid())
+ {
+ // connection closed
+ _cleanup();
+ scd_debug("in_connector: connection closed");
+ return;
+ }
+
+ if (!_reader.is_reading() && !_reader.has_command())
+ {
+ // received an illegal command
+ scd_debug("in_connector: received illegal command");
+ _cleanup();
+ return;
+ }
+
+ if (_reader.has_command())
+ {
+ scd_command* cmd = _reader.get_command();
+
+ if (cmd->get_type() == SCD_CM_REGISTER &&
+ cmd->get_subtype() == SCD_CM_NETSIM)
+ {
+ // register host
+ scd_debug("in_connector: received cmd \"register host\"");
+
+ try
+ {
+ // check if we are the master
+ scd_cont_man_master& master =
+ dynamic_cast<scd_cont_man_master&>(_sim.get_cont_man());
+
+ _sim.get_poller().remove_handler(*this);
+
+ master.connect_slave(*cmd, _socket);
+
+ delete cmd;
+ _is_connecting = false;
+ return;
+ }
+ catch ( std::bad_cast e)
+ {
+ scd_warn("slave tried to register");
+ delete cmd;
+ _cleanup();
+ return;
+ }
+ } // end register host
+ else if (cmd->get_type() == SCD_CM_REGISTER &&
+ cmd->get_subtype() == SCD_CM_CHANNEL)
+ {
+ // register channel
+ scd_debug("in_connector: received cmd \"register channel\"");
+
+ _sim.get_poller().remove_handler(*this);
+
+ _sim.get_chan_man().connect_channel(*cmd, _socket);
+
+ delete cmd;
+ _is_connecting = false;
+ return;
+ } // end register channel
+ else
+ {
+ // received wrong command
+ scd_debug("in_connector: received unknown command");
+ delete cmd;
+ _cleanup();
+ return;
+ }
+ } // end receive command
+ } // end read event
+
+} // handle_sock_ev()
+
+
+const scd_socket& scd_in_connector::get_sock()
+{
+ return *_socket;
+}
+
+
+void scd_in_connector::_cleanup()
+{
+ if (_is_connecting)
+ _sim.get_poller().remove_handler(*this);
+ _socket->close();
+ delete _socket;
+ _is_connecting = false;
+}
--- /dev/null
+#ifndef SCD_IN_CONNECTOR_H
+#define SCD_IN_CONNECTOR_H
+
+#include "scd_socket.h"
+#include "scd_sock_poller.h"
+#include "scd_simulator.h"
+#include "scd_command_reader.h"
+
+/**
+ * Reads a command from a socket handled over by scd_init_listener
+ * and dispatches the connection to either the control or channel manager.
+ * This is used during the initialization phase.
+ */
+class scd_in_connector : public scd_sock_ev_handler_if
+{
+public:
+ /**
+ * Constructor.
+ * \param sim the simulator
+ * \param sock the socket of the connection to read the command from
+ */
+ scd_in_connector(scd_simulator &sim, scd_socket* sock);
+
+ ~scd_in_connector();
+
+ /**
+ * Indicates if this in_connector is still reading the incomming command.
+ * It can be deconstructed when this indicates false.
+ * \return true if this in_connector is still working
+ */
+ bool is_connecting();
+
+ /* scd_sock_ev_handler_if */
+ void handle_sock_ev(sock_ev events);
+ const scd_socket& get_sock();
+
+private:
+ scd_socket* _socket;
+ scd_simulator &_sim;
+ bool _is_connecting;
+ scd_command_reader _reader;
+
+ void _cleanup();
+};
+
+#endif
--- /dev/null
+#include "scd_init_listener.h"
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_in_connector.h"
+
+
+scd_init_listener::scd_init_listener(scd_simulator &sim, uint16_t port):
+ _sim(sim), _host(""), _port(port), _handler(false) {}
+
+
+scd_init_listener::scd_init_listener(scd_simulator &sim,
+ const std::string &host, uint16_t port):
+ _sim(sim), _host(host), _port(port), _handler(false) {}
+
+
+scd_init_listener::~scd_init_listener()
+{
+ cleanup(true);
+ close();
+}
+
+
+void scd_init_listener::listen()
+{
+ if (!_socket.is_valid())
+ {
+ // create listening socket
+ if (!_socket.create())
+ throw scd_exception("creating listening socket failed");
+ if (!_socket.bind(_host, _port))
+ throw scd_exception("binding listening socket failed");
+ if (!_socket.listen())
+ throw scd_exception("listening to socket failed");
+
+ // register socket
+ if (!_handler)
+ {
+ _sim.get_poller().register_handler(*this,
+ SOCK_EV_READ | SOCK_EV_CLOSE);
+ _handler = true;
+ }
+
+ scd_debug("socket listening");
+ }
+ else
+ scd_warn("socket is already listening");
+
+} // listen()
+
+
+void scd_init_listener::close()
+{
+ if (_handler)
+ {
+ _sim.get_poller().remove_handler(*this);
+ _handler = false;
+ }
+
+ if (_socket.is_valid())
+ {
+ _socket.close();
+ scd_debug("listener socket closed");
+ }
+
+} // close()
+
+
+void scd_init_listener::cleanup(bool hard)
+{
+ std::list<scd_in_connector*>::iterator iter;
+
+ for( iter=_connectors.begin(); iter!=_connectors.end();)
+ {
+ if ( hard || !(*iter)->is_connecting() )
+ {
+ delete *iter;
+ iter = _connectors.erase(iter);
+ }
+ else
+ iter++;
+ }
+} // cleanup()
+
+
+void scd_init_listener::handle_sock_ev(sock_ev events)
+{
+ if (events & SOCK_EV_READ)
+ {
+ scd_debug("incomming connection");
+
+ scd_socket* newconn = new scd_socket();
+
+ if (_socket.accept(*newconn))
+ {
+ /* create a new connector that handles the connection
+ * and store it in the list of connectors */
+ scd_in_connector* connector;
+ connector = new scd_in_connector(_sim, newconn);
+ _connectors.push_back(connector);
+ }
+ else
+ {
+ // connection could not be accepted
+ scd_debug("accepting connection failed");
+ delete newconn;
+ }
+ }
+
+ if (events & SOCK_EV_CLOSE)
+ {
+ throw scd_exception("init_listener: experienced an error");
+ }
+
+ if (!_socket.is_valid())
+ {
+ throw scd_exception("init_listener: unexpectedly closed");
+ }
+
+} // sock_ev_handler()
+
+
+const scd_socket& scd_init_listener::get_sock()
+{
+ return _socket;
+}
--- /dev/null
+#ifndef SCD_INIT_LISTENER_H
+#define SCD_INIT_LISTENER_H
+
+#include <list>
+
+#include "scd_sock_poller.h"
+#include "scd_socket.h"
+#include "scd_simulator.h"
+#include "scd_in_connector.h"
+
+/**
+ * Accepts incomming connection during initialization and instanciates
+ * a connector that handles the new connection.
+ */
+class scd_init_listener : public scd_sock_ev_handler_if
+{
+public:
+ /**
+ * Constructor. Binds the listener to the specified TCP port on all
+ * available network interfaces.
+ * \param sim the simulator
+ * \param port TCP port to bind to
+ */
+ scd_init_listener(scd_simulator &sim, uint16_t port);
+
+ /**
+ * Constructor. Binds the listener to the specified TCP port
+ * only on the specified network interface.
+ * \param sim the simulator
+ * \param host IP or domain name of the interface to bind to
+ * \param port TCP port to bind to
+ */
+ scd_init_listener(scd_simulator &sim,
+ const std::string &host, uint16_t port);
+
+ /**
+ * Deconstructor.
+ */
+ virtual ~scd_init_listener();
+
+ /**
+ * Creates the listening socket.
+ * \exception scd_exception if unexpected errors occure
+ */
+ void listen();
+
+ /**
+ * Closes the listening socket.
+ */
+ void close();
+
+ /**
+ * Removes connectors that finished their job. If the optional argument
+ * hard is true all connectors are destroyed independend if they
+ * have finished or not.
+ * \param hard if true all connectors will be destroyed
+ */
+ void cleanup(bool hard = false);
+
+ /* scd_sock_ev_handler_if */
+ void handle_sock_ev(sock_ev events);
+ const scd_socket& get_sock();
+
+private:
+ scd_simulator &_sim;
+ std::string _host;
+ uint16_t _port;
+ scd_socket _socket;
+ std::list<scd_in_connector*>_connectors;
+ bool _handler;
+};
+
+#endif
--- /dev/null
+#include <iostream>
+#include <string>
+
+#include "scd_logging.h"
+
+static scd_loglevel _curr_level = SCD_INFO;
+
+void scd_log(const scd_loglevel &level, const string &str)
+{
+ std::ostream &out = std::clog;
+
+ if (_curr_level > level)
+ return;
+
+ switch(level)
+ {
+ case SCD_DEBUG:
+ out << "debug: ";
+ break;
+ case SCD_INFO:
+ out << "info: ";
+ break;
+ case SCD_WARN:
+ out << "warn: ";
+ break;
+ case SCD_ERROR:
+ out << "error: ";
+ break;
+ default:
+ out << "unknown: ";
+ break;
+ }
+
+ out << str << std::endl;
+}
+
+void scd_set_loglevel(const scd_loglevel &level)
+{
+ _curr_level = level;
+}
--- /dev/null
+#ifndef SCD_LOGGING_H
+#define SCD_LOGGING_H
+
+#include <string>
+using std::string;
+
+/* Loglevels. Default is SCD_INFO */
+typedef int scd_loglevel;
+const scd_loglevel SCD_DEBUG = 0;
+const scd_loglevel SCD_INFO = 1;
+const scd_loglevel SCD_WARN = 2;
+const scd_loglevel SCD_ERROR = 3;
+
+/**
+ * Log message if the current loglevel is low enough.
+ */
+void scd_log(const scd_loglevel &level, const string &str);
+
+/**
+ * Log message with loglevel SCD_DEBUG.
+ */
+inline void scd_debug(const string &str)
+{
+ scd_log(SCD_DEBUG, str);
+}
+
+/**
+ * Log message with loglevel SCD_INFO.
+ */
+inline void scd_info(const string &str)
+{
+ scd_log(SCD_INFO, str);
+}
+
+/**
+ * Log message with loglevel SCD_WARN.
+ */
+inline void scd_warn(const string &str)
+{
+ scd_log(SCD_WARN, str);
+}
+
+/**
+ * Log message with loglevel SCD_ERROR.
+ */
+inline void scd_error(const string &str)
+{
+ scd_log(SCD_ERROR, str);
+}
+
+/**
+ * Set the current loglevel. Events with lower priorities are not logged.
+ */
+void scd_set_loglevel(const scd_loglevel &level);
+
+#endif
--- /dev/null
+#include "scd_out_connector.h"
+
+#include <assert.h>
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+#include "scd_command.h"
+
+
+scd_out_connector::scd_out_connector(scd_simulator& sim, uint16_t type,
+ const std::string& name):
+ _sim(sim), _name(name),
+ _is_connecting(true), _is_connected(false), _has_connection(false)
+{
+ // create socket
+ _socket = new scd_socket;
+ _socket->create();
+
+ // prepare register command (do not send yet)
+ scd_command* cmd = new scd_command(SCD_CM_REGISTER, type, name);
+ _writer = new scd_command_writer();
+ _writer->set_socket(*_socket);
+ _writer->queue_command(cmd);
+}
+
+
+scd_out_connector::~scd_out_connector()
+{
+ close();
+ delete _writer;
+}
+
+
+void scd_out_connector::connect_to(const std::string& host, uint16_t port)
+{
+ _host = host;
+ _port = port;
+
+ // register the handler to check if a connection attempt succeeded
+ _sim.get_poller().register_handler(*this, SOCK_EV_WRITE);
+
+ // start connection attempt
+ _conn_attempt();
+
+} // connect_to()
+
+
+bool scd_out_connector::is_connecting() { return _is_connecting; }
+
+
+bool scd_out_connector::has_connection() { return _has_connection; }
+
+
+scd_socket* scd_out_connector::get_connection()
+{
+ if (_has_connection)
+ {
+ _has_connection = false;
+ return _socket;
+ }
+ else
+ return NULL;
+}
+
+
+void scd_out_connector::process()
+{
+ if (_is_connecting && !_is_connected)
+ {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+
+ // check if an attempt had timed out (i.e. because of "drop" FW policy)
+ if ( _socket->is_connecting() &&
+ (now.tv_sec - _last_con.tv_sec >= SCD_CON_TIMEOUT) )
+ {
+ // close and reopen the socket
+ scd_debug("connecting to " + _host + " timed out");
+ _sim.get_poller().remove_handler(*this);
+ _socket->close();
+ _socket->create();
+ _sim.get_poller().register_handler(*this, 0);
+ }
+
+ // check if it is time to try again
+ if ( !_socket->is_connecting() &&
+ (now.tv_sec - _last_con.tv_sec >= SCD_CON_RETRY) )
+ {
+ scd_debug("reconnecting to " + _host);
+ _conn_attempt();
+ _sim.get_poller().set_ev(*this, SOCK_EV_WRITE);
+ }
+ } // still trying to tcp-connect
+
+} // process()
+
+
+void scd_out_connector::close()
+{
+ if (_is_connecting)
+ {
+ _sim.get_poller().remove_handler(*this);
+ }
+
+ if (_is_connecting || _has_connection)
+ {
+ _socket->close();
+ delete _socket;
+
+ _is_connecting = false;
+ _has_connection = false;
+ }
+
+ _is_connected = false;
+
+} // close()
+
+
+const std::string& scd_out_connector::get_name() const { return _name; }
+
+
+void scd_out_connector::handle_sock_ev(sock_ev events)
+{
+ if (events & SOCK_EV_CLOSE)
+ {
+ // the close event is only polled if _is_connected is true
+ scd_error("outgoing connection closed");
+ close();
+ return;
+ } // end close event
+ else if (events & SOCK_EV_WRITE)
+ {
+ if (!_is_connected)
+ {
+ if (_socket->connected_event())
+ {
+ // connection established
+ scd_debug("ougoing connection established to " + _host);
+ _is_connected = true;
+ _sim.get_poller().set_ev(*this, SOCK_EV_WRITE | SOCK_EV_CLOSE);
+ }
+ else
+ {
+ // connection attempt failed
+ _sim.get_poller().set_ev(*this, 0);
+ return;
+ }
+ }
+
+ assert( _is_connected || !_socket->is_connecting());
+
+ _writer->write();
+ if (!_writer->is_writing())
+ {
+ // done sending the command
+ _is_connecting = false;
+ _has_connection = true;
+ _sim.get_poller().remove_handler(*this);
+ }
+
+ if (!_socket->is_valid())
+ {
+ close();
+ }
+ } // end write event
+
+} // handle_sock_ev()
+
+
+const scd_socket& scd_out_connector::get_sock() { return *_socket; }
+
+
+void scd_out_connector::_conn_attempt()
+{
+ if (_socket->connect(_host, _port))
+ {
+ gettimeofday(&_last_con, NULL);
+ }
+ else
+ {
+ scd_error("unable to connect to " + _host);
+ close();
+ }
+
+} // _conn_attempt()
--- /dev/null
+#ifndef SCD_OUT_CONNECTOR_H
+#define SCD_OUT_CONNECTOR_H
+
+#include <string>
+#include <time.h>
+#include <sys/time.h>
+
+#include "scd_socket.h"
+#include "scd_sock_poller.h"
+#include "scd_simulator.h"
+#include "scd_command_writer.h"
+
+
+const time_t SCD_CON_TIMEOUT = 2;
+const time_t SCD_CON_RETRY = 1;
+
+
+/* forward declaration */
+class scd_simulator;
+
+
+/**
+ * Initiates an outgoing connection and sends the register command
+ * to the other side. If an attempt to connect failes it is
+ * retried after some time. To drive this, process() has to be called
+ * repeatedly.
+ */
+class scd_out_connector : public scd_sock_ev_handler_if
+{
+public:
+ /**
+ * Constructor.
+ * \param sim the simulator
+ * \param type what should be connected (SCD_CM_NETSIM or SCD_CM_CHANNEL)
+ * \param name the name of the ressource to connect (i.e. channel name
+ * or slave name)
+ */
+ scd_out_connector(scd_simulator& sim, uint16_t type,
+ const std::string& name);
+
+ virtual ~scd_out_connector();
+
+ /**
+ * Sets the host to connect to and starts the first connection attempt.
+ *
+ * \param host the IP or hostname to connect to
+ * \param port the port to connect to
+ */
+ void connect_to(const std::string& host, uint16_t port);
+
+ /**
+ * Indicates if this out_connector is still trying to connect or
+ * sending the command.
+ * * \return true if this out_connector is still working
+ */
+ bool is_connecting();
+
+ /**
+ * Indicates if the command has been sent successfully and the registered
+ * connection can be collected.
+ * \return true if a connection is registered
+ */
+ bool has_connection();
+
+ /**
+ * Returns the established and registered connection.
+ */
+ scd_socket* get_connection();
+
+
+ /**
+ * Checks if a time outs have occured. A connection attempt that is running
+ * for more than SCD_CON_TIMEOUT seconds is terminated and failed
+ * connection attempts are retried after SCD_CON_RETRY seconds.
+ */
+ void process();
+
+ /**
+ * Stops to try to connect or terminates an already established
+ * connection.
+ */
+ void close();
+
+ /**
+ * Returns the name of the ressource to connect.
+ */
+ const std::string& get_name() const;
+
+ /* scd_sock_ev_handler_if */
+ void handle_sock_ev(sock_ev events);
+ const scd_socket& get_sock();
+
+private:
+ scd_simulator &_sim;
+ std::string _name;
+ std::string _host;
+ uint16_t _port;
+
+ bool _is_connecting;
+ bool _has_connection;
+ scd_socket* _socket;
+ scd_command_writer* _writer;
+
+ bool _is_connected;
+ struct timeval _last_con;
+
+ void _conn_attempt();
+};
+
+#endif
--- /dev/null
+#ifndef SCD_REM_CHAN_IF_H
+#define SCD_REM_CHAN_IF_H
+
+#include <sys/types.h>
+
+
+/**
+ * Interface for SystemC channels with remote input.
+ */
+class scd_rem_chan_in_if
+{
+public:
+
+ /**
+ * Indicates how many bytes can be received by this channel.
+ */
+ virtual size_t free() const = 0;
+
+ /**
+ * Receive bytes, convert to internal data structures and generate
+ * notifications if necessary.
+ *
+ * \param buf pointer to buffer to read data from
+ * \param len number of bytes to receive (not larger than free())
+ */
+ virtual void receive(const void* buf, size_t len) = 0;
+
+ /**
+ * Virtual deconstructor
+ */
+ virtual ~scd_rem_chan_in_if() {}
+};
+
+
+/**
+ * Interface for SystemC channels with remote output.
+ */
+class scd_rem_chan_out_if
+{
+public:
+
+ /**
+ * Inidcates how many bytes are available to be sent from this channel.
+ */
+ virtual size_t available() const = 0;
+
+ /**
+ * Get the available data to be sent. Does not guarantee that it is
+ * actually sent. At most available() bytes are sent.
+ */
+ virtual const void* send() const = 0;
+
+ /**
+ * Remove bytes from channel that have been successully sent.
+ *
+ * \param len number of bytes that have been sent (not larger than
+ * available())
+ */
+ virtual void remove(size_t len) = 0;
+
+ /**
+ * Virtual deconstructor
+ */
+ virtual ~scd_rem_chan_out_if() {}
+};
+
+#endif
--- /dev/null
+#include "scd_rem_fifo_in.h"
+
+#include <cassert>
+
+#include "scd_logging.h"
+
+
+scd_rem_fifo_in::scd_rem_fifo_in(sc_module_name name, int size):
+ sc_prim_channel(name), _num_elements(0), _first(0), _size(size)
+{
+ assert(size > 0);
+ _data = new char[size];
+}
+
+
+scd_rem_fifo_in::~scd_rem_fifo_in()
+{
+ delete _data;
+}
+
+
+void scd_rem_fifo_in::read(char &c)
+{
+ while (_num_elements == 0)
+ wait(_write_event);
+
+ c = _data[_first];
+ _num_elements--;
+ _first = (_first + 1) % _size;
+}
+
+
+int scd_rem_fifo_in::rtest(int size)
+{
+ return (size <= _num_elements) ? 1 : 0;
+}
+
+
+void scd_rem_fifo_in::reset() { _num_elements = _first = 0; }
+
+
+int scd_rem_fifo_in::num_available() { return _num_elements ;}
+
+
+size_t scd_rem_fifo_in::free() const { return _size - _num_elements; }
+
+
+void scd_rem_fifo_in::receive(const void* buf, size_t len)
+{
+ if (len == 0)
+ return;
+
+ assert(_num_elements + len <= _size);
+
+ for (int i=0; i<len; i++)
+ {
+ _data[(_first + _num_elements) % _size] = *((char*)buf+i);
+ _num_elements++;
+ }
+
+ _write_event.notify();
+}
--- /dev/null
+/*****************************************************************************
+
+ The following code is derived, directly or inror: pointdirectly, from the SystemC
+ source code Copyright (c) 1996-2007 by all Contributors.
+ All Rights reserved.
+
+ The contents of this file are subject to the restrictions and limitations
+ set forth in the SystemC Open Source License Version 2.4 (the "License");
+ You may not use this file except in compliance with such restrictions and
+ limitations. You may obtain instructions on how to receive a copy of the
+ License at http://www.systemc.org/. Software distributed by Contributors
+ under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+ ANY KIND, either express or implied. See the License for the specific
+ language governing rights and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ simple_fifo.cpp -- Simple SystemC 2.0 producer/consumer example.
+
+ From "An Introduction to System Level Modeling in
+ SystemC 2.0". By Stuart Swan, Cadence Design Systems.
+ Available at www.systemc.org
+
+ Original Author: Stuart Swan, Cadence Design Systems, 2001-06-18
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date: Fabian Hugelshofer, ETH Zurich, 13.11.2007
+ Description of Modification: Used code as base for remote fifo channels.
+
+ *****************************************************************************/
+
+#ifndef SCD_REM_FIFO_IN_H_
+#define SCD_REM_FIFO_IN_H_
+
+#include "systemc"
+
+#include "simple_fifo.h" // for read_if
+#include "scd_rem_chan_if.h"
+
+
+/**
+ * FIFO channel with remote input. Data read from this FIFO originates
+ * from another host.
+ */
+class scd_rem_fifo_in : public sc_core::sc_prim_channel, public read_if,
+ public scd_rem_chan_in_if
+{
+public:
+ /**
+ * Constructor.
+ * \param name the name of the channel (is passed to parent constructor)
+ * \param size size of the input buffer in bytes
+ */
+ scd_rem_fifo_in(sc_module_name name, int size);
+
+ virtual ~scd_rem_fifo_in();
+
+ /* read_if */
+ void read(char &c);
+ int rtest(int size);
+ void reset();
+ int num_available();
+
+ /* scd_rem_chan_out_if */
+ size_t free() const;
+ void receive(const void* buf, size_t len);
+
+private:
+ int _size;
+ char* _data;
+ int _num_elements, _first;
+ sc_event _write_event;
+};
+
+#endif
--- /dev/null
+#include "scd_rem_fifo_out.h"
+
+#include <cassert>
+
+#include "scd_logging.h"
+
+
+scd_rem_fifo_out::scd_rem_fifo_out(sc_module_name name, int size):
+ sc_prim_channel(name), _num_elements(0), _first(0), _size(size)
+{
+ assert(size > 0);
+ _data = new char[size];
+}
+
+
+scd_rem_fifo_out::~scd_rem_fifo_out()
+{
+ delete _data;
+}
+
+
+void scd_rem_fifo_out::write(char c)
+{
+ while (_num_elements == _size)
+ wait(_read_event);
+
+ _data[ (_first + _num_elements) % _size ] = c;
+ _num_elements++;
+}
+
+
+int scd_rem_fifo_out::wtest(int size)
+{
+ return (size <= _size - _num_elements) ? 1 : 0;
+}
+
+
+void scd_rem_fifo_out::reset() { _num_elements = _first = 0; }
+
+
+size_t scd_rem_fifo_out::available() const
+{
+ size_t avail;
+
+ if (_num_elements <= _size - _first)
+ avail = _num_elements;
+ else
+ avail = _size - _first;
+
+ return avail;
+}
+
+
+const void* scd_rem_fifo_out::send() const { return _data + _first; }
+
+
+void scd_rem_fifo_out::remove(size_t len)
+{
+ if (len == 0)
+ return;
+
+ assert(_num_elements >= len);
+
+ _first = (_first + len) % _size;
+
+ _num_elements -= len;
+
+ _read_event.notify();
+}
--- /dev/null
+/*****************************************************************************
+
+ The following code is derived, directly or inror: pointdirectly, from the SystemC
+ source code Copyright (c) 1996-2007 by all Contributors.
+ All Rights reserved.
+
+ The contents of this file are subject to the restrictions and limitations
+ set forth in the SystemC Open Source License Version 2.4 (the "License");
+ You may not use this file except in compliance with such restrictions and
+ limitations. You may obtain instructions on how to receive a copy of the
+ License at http://www.systemc.org/. Software distributed by Contributors
+ under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+ ANY KIND, either express or implied. See the License for the specific
+ language governing rights and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ simple_fifo.cpp -- Simple SystemC 2.0 producer/consumer example.
+
+ From "An Introduction to System Level Modeling in
+ SystemC 2.0". By Stuart Swan, Cadence Design Systems.
+ Available at www.systemc.org
+
+ Original Author: Stuart Swan, Cadence Design Systems, 2001-06-18
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date: Fabian Hugelshofer, ETH Zurich, 13.11.2007
+ Description of Modification: Used code as base for remote fifo channels.
+
+ *****************************************************************************/
+
+#ifndef SCD_REM_FIFO_OUT_H_
+#define SCD_REM_FIFO_OUT_H_
+
+#include "systemc"
+
+#include "simple_fifo.h" // for write_if
+#include "scd_rem_chan_if.h"
+
+
+/**
+ * FIFO channel with remote output. Data written to this FIFO endpoint
+ * is transmitted to another host.
+ */
+class scd_rem_fifo_out : public sc_core::sc_prim_channel, public write_if,
+ public scd_rem_chan_out_if
+{
+public:
+ /**
+ * Constructor.
+ * \param name the name of the channel (is passed to parent constructor)
+ * \param size size of the output buffer in bytes
+ */
+ scd_rem_fifo_out(sc_module_name name, int size);
+
+ virtual ~scd_rem_fifo_out();
+
+ /* write_if */
+ void write(char c);
+ int wtest(int size);
+ void reset();
+
+ /* scd_rem_chan_out_if */
+ size_t available() const;
+ const void* send() const;
+ void remove(size_t len);
+
+private:
+ int _size;
+ char* _data;
+ int _num_elements, _first;
+ sc_event _read_event;
+};
+
+#endif
--- /dev/null
+#include "scd_simulator.h"
+
+#include <unistd.h>
+#include <assert.h>
+
+#include "systemc"
+
+#include "scd_cont_man_master.h"
+#include "scd_cont_man_slave.h"
+#include "scd_init_listener.h"
+#include "scd_logging.h"
+
+
+scd_simulator::scd_simulator(const std::string& name,
+ const std::string &loc_host, uint16_t loc_port, bool master):
+ _name(name), _loc_host(loc_host), _loc_port(loc_port)
+{
+ _poller = new scd_sock_poller;
+
+ if (master == SCD_MASTER)
+ _cont_man = new scd_cont_man_master(*this);
+ else
+ _cont_man = new scd_cont_man_slave(*this);
+
+ _chan_man = new scd_chan_man(*this);
+}
+
+
+scd_simulator::scd_simulator(const std::string& name, uint16_t loc_port,
+ bool master):
+ _name(name), _loc_host(""), _loc_port(loc_port)
+{
+ _poller = new scd_sock_poller;
+
+ if (master == SCD_MASTER)
+ _cont_man = new scd_cont_man_master(*this);
+ else
+ _cont_man = new scd_cont_man_slave(*this);
+
+ _chan_man = new scd_chan_man(*this);
+}
+
+
+scd_simulator::~scd_simulator()
+{
+ delete _chan_man;
+ delete _cont_man;
+ delete _poller;
+}
+
+
+const std::string& scd_simulator::get_name() const { return _name; }
+
+
+scd_sock_poller& scd_simulator::get_poller() { return *_poller; }
+
+
+scd_chan_man& scd_simulator::get_chan_man() { return *_chan_man; }
+
+
+scd_cont_man& scd_simulator::get_cont_man() { return *_cont_man; }
+
+
+bool scd_simulator::init()
+{
+ scd_info("initialization start");
+
+ /* open port for incomming connections */
+ scd_init_listener listener(*this, _loc_host, _loc_port);
+ listener.listen();
+
+ /*
+ * init until the initialization failed or chan_man and cont_man are
+ * successfully initiated
+ */
+ while ( !_cont_man->failed() &&
+ ( !_chan_man->ready() || !_cont_man->active() ) )
+ {
+ // poll the sockets and execute callback handlers
+ _poller->process();
+
+ // connect channels
+ _chan_man->init_process();
+
+ // process state transitions
+ _cont_man->process();
+
+ /* as we might be waiting for a peer coming up we can not use
+ * a blocking poll as errors would always exist and the poller would
+ * wake up immediately
+ * => sleep some milliseconds
+ */
+ usleep(50);
+ }
+
+ listener.close();
+
+ if (_cont_man->failed())
+ {
+ scd_error("initialization failed");
+ return false;
+ }
+ else
+ {
+ scd_info("initialization done");
+ return true;
+ }
+
+} // init()
+
+
+bool scd_simulator::start()
+{
+ scd_info("simulation start");
+
+ /* first delta cycle to initialize the SystemC scheduler
+ * else the _pending*() functions would fail */
+ sc_core::sc_start(sc_core::SC_ZERO_TIME);
+
+ while (_cont_man->active())
+ {
+ /* signalize the simulation state to the controller */
+ if (_pending())
+ {
+ if (_pending_now())
+ {
+ // events in this time step
+ _cont_man->set_busy();
+ }
+ else
+ {
+ // signalize time step until next event
+ sc_core::sc_time step;
+ step = _next_time() - sc_core::sc_time_stamp();
+ _cont_man->set_idle(step);
+ }
+ }
+ else
+ _cont_man->set_done();
+
+ // check for state changes
+ _cont_man->process();
+
+ /* run simulation if something to do and in right state */
+ if (_cont_man->busy())
+ {
+ // simulate one delta cycle
+ sc_core::sc_start(sc_core::SC_ZERO_TIME);
+
+ // check if we have to wait for new socket events
+ _chan_man->process();
+
+ // poll the sockets to induce transmissions
+ _poller->process();
+ }
+ else
+ {
+ if (_cont_man->advance_time())
+ {
+ sc_core::sc_time step = _cont_man->get_time_step();
+ // advance simulation time, nothing should actually be simulated
+ sc_start(step);
+ scd_info("time advanced by " + step.to_string() + " to "
+ + sc_core::sc_time_stamp().to_string() );
+ }
+ else if ( _cont_man->active() )
+ {
+ // wait for activity on sockets
+ _poller->wait_process();
+ }
+ }
+
+ } // while simulation is running
+
+ /* simulation terminated */
+
+ if (_cont_man->failed())
+ {
+ scd_error("simulation failed");
+ return false;
+ }
+ else
+ {
+ scd_info("simulation done");
+ return true;
+ }
+
+} // start()
+
+
+/**
+ * Returns true if events exist at current simulation time.
+ */
+bool scd_simulator::_pending_now()
+{
+ return sc_core::sc_pending_activity_at_current_time();
+}
+
+
+/**
+ * Returns true if events exist at current or later simulation time.
+ */
+bool scd_simulator::_pending()
+{
+ sc_core::sc_time next = _next_time();
+ return ( (next != sc_core::SC_ZERO_TIME) || _pending_now() );
+}
+
+
+/**
+ * Returns the time of the next earliest timed event
+ * or SC_ZERO_TIME if no such event exists.
+ */
+const sc_core::sc_time scd_simulator::_next_time()
+{
+ return sc_core::sc_get_curr_simcontext()->next_time();
+}
+
--- /dev/null
+#ifndef SCD_SIMULATOR_H
+#define SCD_SIMULATOR_H
+
+#include <sys/types.h>
+#include <string>
+
+#include "scd_sock_poller.h"
+#include "scd_chan_man.h"
+#include "scd_cont_man.h"
+
+
+/* forward declaration */
+class scd_chan_man;
+class scd_cont_man_if;
+
+
+/**
+ * Simulator to run a distributed SystemC simulation. First the
+ * channel with remote endpoints, the slave controllers and the
+ * master controller have to be registered with the channel manager
+ * and the control manager. Second the simulation has to be
+ * initialized and third the simulation can be started.
+ */
+class scd_simulator
+{
+public:
+
+ /**
+ * Constructor. Binds the simulator to the specified TCP port
+ * only on the specified network interface.
+ * \param name the name of this simulator
+ * \param loc_host IP or domain name of the interface to bind to
+ * \param loc_port TCP port to bind to
+ * \bool master SCD_MASTER if this simulator is the master, else
+ * SCD_SLAVE
+ */
+ scd_simulator(const std::string& name, const std::string &loc_host,
+ uint16_t loc_port, bool master);
+
+ /**
+ * Constructor. Binds the simulator to the specified TCP port on all
+ * available network interfaces.
+ * \param name the name of this simulator
+ * \param loc_port TCP port to bind to
+ * \bool master SCD_MASTER if this simulator is the master, else
+ * SCD_SLAVE
+ */
+ scd_simulator(const std::string& name, uint16_t loc_port, bool master);
+
+ virtual ~scd_simulator();
+
+
+ /**
+ * Returns the name of this simulator.
+ */
+ const std::string& get_name() const;
+
+ /**
+ * Returns the socket poller of this simulation.
+ */
+ scd_sock_poller& get_poller();
+
+ /**
+ * Returns the channel manager of this simulation.
+ */
+ scd_chan_man& get_chan_man();
+
+ /**
+ * Returns the control manager of this simulation.
+ */
+ scd_cont_man& get_cont_man();
+
+ /**
+ * Initializes the distributed simulation. Connects all remote channels
+ * and the control infrastructure. The channels, the slaves and the master
+ * have to be registered before initializating. A simulation can only
+ * be initialized once.
+ */
+ bool init();
+
+ /**
+ * Runs the simulation until an error occures or no more events
+ * exist globally. A simulation can only be started once.
+ */
+ bool start();
+
+
+private:
+ scd_sock_poller* _poller;
+ scd_chan_man* _chan_man;
+ scd_cont_man* _cont_man;
+
+ std::string _name;
+ std::string _loc_host;
+ uint16_t _loc_port;
+
+ /* member functions */
+
+ /**
+ * Indicates if events exist for the current simulation time.
+ * \return true if events exist for the current time
+ */
+ bool _pending_now();
+
+ /**
+ * Indicates if events exist in the event queues.
+ * \return true if events exist
+ */
+ bool _pending();
+
+ /**
+ * Returns the absolute time of the next event in the queues.
+ * \retunrs the absoulte time of the next event or 0 if no such event exists
+ */
+ const sc_core::sc_time _next_time();
+};
+
+#endif
--- /dev/null
+#include "scd_sock_poller.h"
+
+#include <algorithm>
+#include <errno.h>
+#include <string>
+#include <string.h>
+
+#include "scd_exception.h"
+#include "scd_logging.h"
+
+
+bool scd_sock_poller::register_handler(scd_sock_ev_handler_if& handler,
+ sock_ev events)
+{
+ // can not register the same handler twice
+ if (_handler_exists(handler))
+ {
+ scd_warn("socket handler already registered while registering");
+ return false;
+ }
+
+ // register handler
+ _handlers.push_back(&handler);
+
+ // register socket and events
+ struct pollfd fd;
+ fd.fd = handler.get_sock()._socket;
+ fd.events = events;
+ _events.push_back(fd);
+ return true;
+
+} // register_handler()
+
+
+bool scd_sock_poller::remove_handler(const scd_sock_ev_handler_if &handler)
+{
+ int idx = _get_index(handler);
+
+ // check if handler was found
+ if (idx == -1)
+ {
+ scd_warn("socket handler not registered while removing poll handler");
+ return false;
+ }
+
+ // remove events and handler from vectors
+ _events.erase(_events.begin() + idx);
+ _handlers.erase(_handlers.begin() + idx);
+
+ return true;
+
+} // remove_handler()
+
+
+bool scd_sock_poller::set_ev(const scd_sock_ev_handler_if &handler,
+ sock_ev events)
+{
+ int idx = _get_index(handler);
+
+ if (idx == -1)
+ {
+ scd_warn("socket handler not registered while setting poll events");
+ return false;
+ }
+
+ _events[idx].events = events;
+
+ return true;
+} // set_ev()
+
+
+bool scd_sock_poller::get_ev(const scd_sock_ev_handler_if &handler,
+ sock_ev &events) const
+{
+ int idx = _get_index(handler);
+
+ if (idx == -1)
+ {
+ scd_warn("socket handler not registered while getting poll events");
+ return false;
+ }
+
+ events = _events[idx].events;
+
+ return true;
+
+} // get_ev()
+
+
+bool scd_sock_poller::wait(int ms)
+{
+ int ret = _poll(ms);
+ if (ret > 0)
+ return true;
+ else
+ return false;
+}
+
+
+bool scd_sock_poller::process()
+{
+ int ret = _poll(0);
+
+ if (ret != 0) // events occured
+ {
+ _callback();
+ return true;
+ }
+ else
+ return false;
+
+} // process()
+
+
+void scd_sock_poller::wait_process()
+{
+ _poll(-1);
+ _callback();
+
+} // wait_process()
+
+
+bool scd_sock_poller::_handler_exists(const scd_sock_ev_handler_if &handler)
+ const
+{
+ std::vector<scd_sock_ev_handler_if*>::const_iterator iter;
+
+ iter = std::find(_handlers.begin(), _handlers.end(), &handler);
+
+ if (iter == _handlers.end())
+ return false;
+ else
+ return true;
+
+} // _handler_exists()
+
+
+int scd_sock_poller::_get_index(const scd_sock_ev_handler_if &handler) const
+{
+ std::vector<scd_sock_ev_handler_if*>::const_iterator iter;
+
+ iter = std::find(_handlers.begin(), _handlers.end(), &handler);
+
+ if (iter == _handlers.end())
+ {
+ // handler not found
+ return -1;
+ }
+ else
+ {
+ // return index (random access iterator)
+ return iter - _handlers.begin();
+ }
+
+} // _get_index()
+
+
+int scd_sock_poller::_poll(int ms)
+{
+ int ret;
+
+ if (ms < 0 && _events.size() == 0)
+ {
+ scd_debug("immediately returning form infinite poll: no events to watch");
+ return 0;
+ }
+
+ do
+ {
+ ret = poll(&_events[0], _events.size(), ms);
+ if (ret == -1 && errno != EINTR)
+ {
+ std::string error("poll(): ");
+ error += std::string(strerror(errno));
+ throw scd_exception(error);
+ }
+ }
+ while (ret == -1 && errno == EINTR);
+
+ return ret;
+
+} // _poll()
+
+
+void scd_sock_poller::_callback()
+{
+ /* called handlers might remove themselves. as the order
+ * should not break we operate on copies here */
+ std::vector<pollfd> events_cpy = _events;
+ std::vector<scd_sock_ev_handler_if*> handlers_cpy = _handlers;
+
+ // for all handlers
+ for (int i=0; i<events_cpy.size(); i++)
+ {
+ if (events_cpy[i].events & events_cpy[i].revents)
+ {
+ // this event occured => callback handler
+ handlers_cpy[i]->handle_sock_ev(events_cpy[i].revents);
+ }
+ } // for all events
+} // _callback()
--- /dev/null
+#ifndef SCD_SOCK_POLLER_H
+#define SCD_SOCK_POLLER_H
+
+#include <vector>
+#include "poll.h"
+
+#include "scd_socket.h"
+
+
+typedef short sock_ev;
+const sock_ev SOCK_EV_READ = POLLIN;
+const sock_ev SOCK_EV_WRITE = POLLOUT;
+const sock_ev SOCK_EV_CLOSE = POLLERR | POLLHUP | POLLNVAL;
+
+
+/**
+ * Interface for classes able to handle socket events.
+ */
+class scd_sock_ev_handler_if
+{
+public:
+ /**
+ * Executes the handler for socket events that have been registered
+ * and have ocured. Callback carried out by scd_sock_poller.
+ *\param events the events that occured
+ */
+ virtual void handle_sock_ev(sock_ev events) = 0;
+
+ /**
+ * Returns the socket that should be watched. The socket must
+ * be the same as long the handler is registered.
+ */
+ virtual const scd_socket &get_sock() = 0;
+
+ virtual ~scd_sock_ev_handler_if() {};
+};
+
+
+/**
+ * Dispatcher that watches sockets and executes call backs if watched
+ * event occure. Socket events (sock_ev) are an OR combination of flags
+ * supported by ::poll. See "man 2 poll". The watched events for a specific
+ * event handler stay watched until the events are overwritten or the handler
+ * is removed.
+ */
+class scd_sock_poller
+{
+public:
+ /**
+ * Register a socket event handler (a class handling socket events).
+ * Optionally the events to watch can be specified.
+ * \param handler the object that wants to watch a socket
+ * \param events (optional) the events to watch
+ * \return true if the handler could be registered succesfully
+ */
+ bool register_handler(scd_sock_ev_handler_if &handler, sock_ev events = 0);
+
+ /**
+ * Remove a socket event handler. The socket is not watched anymore.
+ * \param the object that has previously been registered
+ * \return false if no such handler was registered
+ */
+ bool remove_handler(const scd_sock_ev_handler_if &handler);
+
+ /**
+ * Set events to watch. The events expire only when overwritten
+ * by calling this function again or by removing the handler.
+ * \param handler the handler that has been registered before
+ * \param events the events the handler is interested in
+ * \return false if the handler has not been registered before
+ */
+ bool set_ev(const scd_sock_ev_handler_if &handler, sock_ev events);
+
+ /**
+ * Gets the events that are currently watched for the handler.
+ * \param the handler to get the watched events for
+ * \param events the variable where the watched events are written to
+ * \return false if the handler has not been registered before
+ */
+ bool get_ev(const scd_sock_ev_handler_if &handler, sock_ev &events) const;
+
+ /**
+ * Wait (blocking) for registered events or a timeout to occure.
+ * No callbacks are executed.
+ * \param milis timeout in milliseconds to wait for events, if omitted
+ * or -1 it is waited until events occure
+ * \return true if events occured, false otherwise
+ * \exception scd_exception if unexpected errors occured
+ */
+ bool wait(int ms = -1);
+
+ /**
+ * Check if events occured and callback the affected handlers.
+ * \return true if some events occured
+ * \exception scd_exception if unexcpected errors occured
+ */
+ bool process();
+
+ /**
+ * Wait (blocking) for registered events to occure and callback the
+ * affected handlers.
+ * \exception scd_exception if unexcpected errors occured
+ */
+ void wait_process();
+
+private:
+ /* member variables */
+ std::vector<scd_sock_ev_handler_if *> _handlers;
+ std::vector<struct pollfd> _events;
+
+ /* member functions */
+
+ /**
+ * Checks if a handler is already registered.
+ * \param handler the handler to check for existence
+ * \return true if the handler has been registered before
+ */
+ bool _handler_exists(const scd_sock_ev_handler_if& handler) const;
+
+ /**
+ * Returns the index of an event handler in the vector. This is the same
+ * index as the corresponding pollfd.
+ * \param handler the handler to get the index of
+ * \return the index of the handler or -1 if it could not be found
+ */
+ int _get_index(const scd_sock_ev_handler_if& handler) const;
+
+ /**
+ * Polls during a specified amount of time.
+ * \param ms miliseconds to block (-1 for infinite)
+ * \exception scd_exception if an unexpected error occured
+ * \return number of sockets for witch events occured
+ */
+ int _poll(int ms);
+
+ /**
+ * Calls handlers back for which events occured.
+ */
+ void _callback();
+};
+
+//scd_sock_poller* scd_get_sock_poller();
+
+#endif
--- /dev/null
+#include "scd_socket.h"
+
+#include <sys/socket.h>
+#include <netinet/tcp.h> // for TCP_NODELAY
+#include <cerrno>
+#include <fcntl.h>
+#include <cassert>
+
+#include "scd_logging.h"
+#include "scd_exception.h"
+
+scd_socket::scd_socket()
+{
+ _socket = -1;
+ _is_connecting = false;
+ _is_connected = false;
+}
+
+scd_socket::~scd_socket() {}
+
+bool scd_socket::is_valid() const
+{
+ return (_socket != -1);
+}
+
+bool scd_socket::create()
+{
+ // check if socket already created before
+ if ( is_valid() )
+ {
+ return false;
+ }
+
+ // create TCP socket
+ _socket = socket(PF_INET, SOCK_STREAM, 0);
+
+ assert(is_valid());
+
+ _set_blocking(false);
+
+ _is_connecting = false;
+ _is_connected = false;
+
+ return true;
+
+} // create()
+
+void scd_socket::close()
+{
+ if ( is_valid() )
+ {
+ ::close(_socket);
+ }
+
+ _socket = -1;
+ _is_connecting = false;
+ _is_connected = false;
+}
+
+bool scd_socket::bind(const std::string &loc_name, const uint16_t loc_port)
+{
+ int ret;
+
+ if ( ! is_valid() )
+ {
+ return false;
+ }
+
+ // prepare the local address
+ sockaddr_in loc_addr;
+ if ( !_get_sockaddr(loc_addr, loc_name, loc_port) )
+ {
+ return false;
+ }
+
+ // set socket reusable (to recreate listener without timeout)
+ int on = 1;
+ ret = setsockopt( _socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
+ if (ret == -1)
+ {
+ throw scd_exception("setsockopt()", errno);
+ }
+
+ ret = ::bind( _socket, reinterpret_cast<struct sockaddr*>(&loc_addr),
+ sizeof( loc_addr ) );
+
+ if ( ret == -1 )
+ {
+ switch(errno)
+ {
+ case EACCES:
+ scd_error("must be root to bind to desired port");
+ break;
+ case EADDRINUSE:
+ scd_error("unable to bind as the address is already in use");
+ break;
+ default:
+ throw scd_exception("bind()", errno);
+ }
+ return false;
+ }
+
+ return true;
+
+} // bind()
+
+
+bool scd_socket::bind(const uint16_t loc_port)
+{
+ return bind("", loc_port);
+} // bind()
+
+
+bool scd_socket::listen()
+{
+ int ret;
+
+ if ( !is_valid() )
+ {
+ return false;
+ }
+
+ ret = ::listen(_socket, SCD_MAXCONN);
+
+ if (ret == -1)
+ {
+ throw scd_exception("listen()", errno);
+ }
+
+ return true;
+} // listen()
+
+bool scd_socket::accept(scd_socket &new_sock)
+{
+ int ret;
+
+ if ( !is_valid() )
+ {
+ return false;
+ }
+
+ ret = ::accept(_socket, NULL, NULL);
+
+ if (ret < 0)
+ {
+ switch (errno)
+ {
+ case EAGAIN:
+ case ECONNABORTED:
+ case EINTR:
+ case EPROTO:
+ return false;
+ break;
+ default:
+ throw scd_exception("accept()", errno);
+ break;
+ }
+ }
+ else
+ {
+ new_sock._is_connected = true;
+ new_sock._socket = ret;
+ new_sock._set_blocking(false);
+ #ifdef TCP_NODELAY
+ new_sock._set_nodelay();
+ #endif
+ }
+
+ return true;
+
+} // accept()
+
+
+bool scd_socket::connect(const std::string &rem_name, const uint16_t rem_port)
+{
+ int ret;
+
+ if ( !is_valid() || _is_connecting || _is_connected )
+ return false;
+
+ sockaddr_in rem_addr;
+ if ( !_get_sockaddr(rem_addr, rem_name, rem_port) )
+ return false;
+
+ ret = ::connect(_socket, reinterpret_cast<const sockaddr*>(&rem_addr),
+ sizeof(rem_addr));
+
+ if (ret == -1)
+ {
+ switch(errno)
+ {
+ case EINPROGRESS:
+ _is_connecting = true;
+ break;
+ case ECONNABORTED:
+ case ECONNREFUSED:
+ case EINTR:
+ case ENETUNREACH:
+ case ETIMEDOUT:
+ break;
+ case EALREADY: // should be prevented by _is_connecting
+ default:
+ throw scd_exception("connect()", errno);
+ break;
+ }
+ }
+ else // ret == 0
+ {
+ _is_connected = true;
+ _is_connecting = false;
+ }
+
+ return true;
+
+} // connect()
+
+bool scd_socket::is_connecting()
+{
+ if ( !is_valid() || !_is_connecting || _is_connected )
+ return false;
+
+ return true;
+
+} // is_connecting()
+
+
+bool scd_socket::is_connected()
+{
+ if ( !is_valid() || _is_connecting || !_is_connected)
+ return false;
+
+ return true;
+
+} // is_connecting()
+
+
+bool scd_socket::connected_event()
+{
+ if (_is_connected)
+ return true;
+
+ if ( !is_valid() )
+ {
+ scd_warn("write event occured on an invalid socket");
+ return false;
+ }
+ else if ( !_is_connecting )
+ {
+ scd_warn("checking connected event while not connecting");
+ return false;
+ }
+
+ // get possible errors from connection attempt
+ int err, ret;
+ socklen_t err_size = sizeof(err);
+ ret = getsockopt(_socket, SOL_SOCKET, SO_ERROR, &err, &err_size);
+
+ if (ret == -1)
+ {
+ throw scd_exception("getsockopt()", errno);
+ }
+
+ // handle errors
+ switch(err)
+ {
+ case 0:
+ // connection established
+ _is_connecting = false;
+ _is_connected = true;
+ #ifdef TCP_NODELAY
+ _set_nodelay();
+ #endif
+ return true;
+ break;
+ case ECONNABORTED:
+ case ECONNREFUSED:
+ case EINTR:
+ case ENETUNREACH:
+ case ETIMEDOUT:
+ // connection attempt failed
+ _is_connecting = false;
+ return false;
+ break;
+ case EINPROGRESS:
+ // should not be possible as we received a completion event
+ throw scd_exception("checking connected event while still connecting");
+ break;
+ case EALREADY: // should be prevented by _is_connecting
+ default:
+ throw scd_exception("connect()", errno);
+ break;
+ }
+
+ // not reached
+} //connected_event()
+
+
+size_t scd_socket::send(const void* buf, size_t len)
+{
+ ssize_t ret;
+
+ if ( !is_valid() || len == 0 || !_is_connected )
+ return 0;
+
+ ret = ::send(_socket, buf, len, MSG_NOSIGNAL);
+
+ if (ret < 0)
+ {
+ switch(errno)
+ {
+ case ECONNRESET:
+ case EPIPE:
+ case ETIMEDOUT:
+ close();
+ break;
+ case EWOULDBLOCK:
+ break;
+ default:
+ throw scd_exception("send()", errno);
+ break;
+ }
+ return 0;
+ }
+ else
+ return ret;
+
+} // send()
+
+size_t scd_socket::recv(void* buf, size_t len)
+{
+ ssize_t ret;
+
+ if ( !is_valid() || len == 0 || !_is_connected)
+ return 0;
+
+ ret = ::recv(_socket, buf, len, MSG_NOSIGNAL);
+
+ if (ret < 0)
+ {
+ switch(errno)
+ {
+ case ETIMEDOUT:
+ close();
+ break;
+ case EAGAIN:
+ case EINTR:
+ break;
+ case ENOTCONN:
+ default:
+ throw scd_exception("recv()", errno);
+ break;
+ }
+ return 0;
+ }
+ else if (ret == 0)
+ {
+ close();
+ return 0;
+ }
+ else
+ return ret;
+
+} // recv()
+
+bool scd_socket::_get_sockaddr(sockaddr_in &addr, const std::string &name,
+ const uint16_t port) const
+{
+ // flush addr
+ memset( &addr, 0, sizeof(addr) );
+
+ /* set content */
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons( port );
+ if ( name.empty() )
+ {
+ // bind to all local addresses
+ addr.sin_addr.s_addr = INADDR_ANY;
+ }
+ else
+ {
+ // bint to specified address only
+ struct hostent* he;
+
+ // resolve name
+ he = gethostbyname2(&name[0], AF_INET);
+ if (he == NULL)
+ return false;
+
+ // copy address (network order)
+ addr.sin_addr.s_addr =
+ reinterpret_cast<struct in_addr*>(he->h_addr_list[0])->s_addr;
+ }
+
+ return true;
+
+} // _get_sockaddr()
+
+
+bool scd_socket::_set_blocking(const bool mode)
+{
+ if ( !is_valid() )
+ {
+ return false;
+ }
+
+ int opts = fcntl( _socket, F_GETFL );
+
+ if ( opts < 0 )
+ {
+ throw scd_exception("fcntl()", errno);
+ }
+
+ if ( !mode )
+ opts = ( opts | O_NONBLOCK );
+ else
+ opts = ( opts & ~O_NONBLOCK );
+
+ fcntl( _socket, F_SETFL,opts );
+
+ return true;
+
+} //_set_blocking()
+
+
+bool scd_socket::_set_nodelay()
+{
+ if ( !is_valid())
+ return false;
+
+ // disable Nagle algorithm
+ int on = 1;
+ int ret = setsockopt( _socket, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on) );
+ if (ret == -1)
+ {
+ throw scd_exception("setsockopt()", errno);
+ }
+
+ return true;
+}
--- /dev/null
+#ifndef SCD_SOCKET_H
+#define SCD_SOCKET_H
+
+#include <string>
+#include <sys/types.h>
+#include <netdb.h>
+
+const int SCD_MAXCONN = 100;
+
+// forward declaration for friends
+class scd_sock_poller;
+
+/**
+ * Berkeley TCP socket API wrapper class. The socket is put into non blocking
+ * mode.
+ */
+class scd_socket
+{
+ friend class scd_sock_poller;
+
+public:
+ scd_socket();
+ virtual ~scd_socket();
+
+ /**
+ * Returns true if this socket has been successfully created and
+ * has not been closed since then. Use this function to check if an
+ * error occured.
+ */
+ bool is_valid() const;
+
+ /**
+ * Creates the socket.
+ * \return false if the socket is already valid
+ * \exception scd_exception if unexpected errors occured
+ */
+ bool create();
+
+ /**
+ * Closes the socket and marks it as invalid.
+ */
+ void close();
+
+ /**
+ * Binds the socket to a local address and port.
+ * \param loc_name the local IP or hostname or empty string
+ * \param loc_port the local port or 0
+ * \return false if the socket is not valid or an invalid address
+ * was specified
+ * \exception scd_exception if ::bind() failed for unexpected reason
+ */
+ bool bind(const std::string &loc_name, const uint16_t loc_port);
+
+ /**
+ * Binds the socket to a port.
+ * \param loc_port the local port
+ * \exception scd_exception if ::bind() failed for unexpected reason
+ * \return false if the sockat is not valid
+ */
+ bool bind(const uint16_t loc_port);
+
+ /**
+ * Marks a previously bound socket as listening.
+ * \return false if the socket is not valid
+ * \exception scd_exception if ::listen() failed
+ */
+ bool listen();
+
+ /**
+ * Accept a new connection from a listening socket.
+ * \param new_sock the object to hold the new connection
+ * \return true if a new connection was accepted
+ * \exception scd_exception if unexpected errors occured
+ */
+ bool accept(scd_socket &new_sock);
+
+ /**
+ * Initiates a connection attempt to a remote host. Use is_connecting()
+ * to check whether this attempt is still in progress or is_connected()
+ * to check whether the socket is connected. If the connection attempt
+ * is in progress, the socket has to be polled for a write event.
+ * If this event occures its handler shall call connected_event()
+ * to check if the connection was established successully.
+ * It is not possible to try to connect again if the write event
+ * is not polled and processed by calling connected_event() after
+ * is_connecting() has indicated that the attempt is still in progress.
+ * \param rem_name the hostname of the remote host (IP or host name)
+ * \param rem_port the port to connect to
+ * \return true if the connection attempt was started successfully,
+ * false if the hostname could not be resolved or a connection attempt
+ * was not possible
+ * \exception scd_exception if unexpected errors occured
+ */
+ bool connect(const std::string &rem_name, const uint16_t rem_port);
+
+ /**
+ * Indicates if a previous connection attempt is still in progress.
+ * \return true if a conneciton attempt is still in progress
+ */
+ bool is_connecting();
+
+ /**
+ * Indicates if this socket is connected to a peer either while it has
+ * been accepted from an incoming connection or the outgoing connection
+ * is established.
+ * \return true if the socket is valid and connected
+ */
+ bool is_connected();
+
+ /**
+ * Check if a connection attempt has succeeded on a write event. Shall
+ * only be called from the write event handler. Especially after a
+ * connection attempt was in progress. Can also be called if the
+ * connection has already been established.
+ * \return true if the socket is valid and the connection is established
+ * \exception scd_exception if unexpected errors occured
+ */
+ bool connected_event();
+
+ /**
+ * Tries to send at most len data from the buffer.
+ * Might close the socket on errors.
+ * \return the number of successfully sent bytes
+ * \exception scd_exception if unexpected errors occured
+ */
+ size_t send(const void* buf, size_t len);
+
+ /**
+ * Tries to receive at most len data to the buffer.
+ * Might close the socket on errors.
+ * \return the number of successfully received bytes
+ * \exception scd_exception if unexpected errors occured
+ */
+ size_t recv(void* buf, size_t len);
+
+
+private:
+ /* member variables */
+
+ int _socket;
+ bool _is_connecting;
+ bool _is_connected;
+
+ /* member functions */
+
+ /**
+ * Initializes a sockaddr_in struct. Can resolve hostnames.
+ */
+ bool _get_sockaddr(sockaddr_in &addr, const std::string &name,
+ const uint16_t port) const;
+
+ /**
+ * Sets the socket in blocking or non blocking mode.
+ * \param mode true to set blocking mode
+ * \return false if the socket is not valid
+ * \exception scd_exception if unexpected errors occured
+ */
+ bool _set_blocking(const bool mode);
+
+ /**
+ * Disables the Nagle algorithm which buffers outgoing data up to 200ms
+ * before sending it. Disabling causes more network traffic but
+ * decreases the delay.
+ */
+ bool _set_nodelay();
+};
+
+#endif
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Code generator.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: ProtothreadMakefileVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.protothread;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class ProtothreadMakefileVisitor extends PNVisitor {
+
+ /**
+ *
+ */
+ public ProtothreadMakefileVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ ps.println("CXX = g++");
+ ps.println("CXXFLAGS = -g -Wall");
+ ps.println("COMPILE = ${CXX} ${CXXFLAGS} -c");
+ ps.println("LINK = ${CXX}");
+ ps.println("LIB_INC = -Ilib -Iwrappers");
+ ps.println();
+ ps.println("src := $(wildcard lib/*.cpp) "
+ + "$(wildcard wrappers/*.cpp) $(wildcard *.cpp)");
+ ps.println("obj = $(src:.cpp=.o)");
+ ps.println();
+ ps.println("app : ${obj} ${src}");
+ ps.println("\t${LINK} -o " + _name + " $(obj)");
+ ps.println();
+ ps.println("%.o :");
+ ps.println("\t${COMPILE} -o $(*D)/$(*F).o $(*D)/$(*F).cpp "
+ + "$(LIB_INC)");
+ ps.println();
+ ps.println("clean :");
+ ps.println("\trm ${obj}");
+ }
+ catch (IOException e) {
+ System.out.println(" Protothread Makefile Visitor: "
+ + "exception occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ protected String _name = "sc_application";
+}
+
--- /dev/null
+/* $Id: ProtothreadModuleVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.protothread;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * the main program.
+ */
+public class ProtothreadModuleVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public ProtothreadModuleVisitor(String dir) {
+ _dir = dir;
+ }
+
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "sc_application.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ _code = new CodePrintStream(file);
+
+ _code.printPrefixln("#include \"pt.h\"");
+ _code.printPrefixln("#include \"Fifo.h\"");
+ _code.printPrefixln("#include \"WindowedFifo.h\"");
+ for (String basename : x.getProcessBasenames()) {
+ _code.printPrefixln("#include \"" + basename
+ + "Wrapper.h\"");
+ }
+
+ _code.println();
+ _code.printPrefixln("int main(void)");
+ _code.printLeftBracket();
+
+ //instantiate channels
+ for (Channel c : x.getChannelList()) {
+ if (c.getType().equals("fifo")) {
+ _code.printPrefixln("Fifo " + c.getName() + "("
+ + c.getSize() * c.getTokenSize() + ");");
+ } else if (c.getType().equals("wfifo")) {
+ _code.printPrefixln("WindowedFifo " + c.getName() + "("
+ + c.getSize() * c.getTokenSize() + ");");
+ }
+ }
+ _code.println();
+
+ //instantiate processes
+ for (Process p : x.getProcessList()) {
+ _code.printPrefix("int " + p.getName()
+ + "Indices[] = { ");
+ Vector<Integer> iteratorIndex =
+ p.getIteratorIndices();
+ if (iteratorIndex.size() < 4) {
+ while (iteratorIndex.size() < 4) {
+ iteratorIndex.add(-1);
+ }
+ } else if (iteratorIndex.size() > 4) {
+ new RuntimeException("Error: Currently not more than "
+ + "4 iterator dimensions are supported."
+ + "Consider revising " + p.getBasename()
+ + ".");
+ }
+ for (int i = 0; i < 4; i++) {
+ if (i < 3) {
+ _code.print(iteratorIndex.elementAt(i) + ", ");
+ } else {
+ _code.println(iteratorIndex.elementAt(i) + " };");
+ }
+ }
+ _code.printPrefixln(p.getBasename() + "Wrapper *"
+ + p.getName() + " = new "
+ + p.getBasename() + "Wrapper(\""
+ + p.getName() + "\", "
+ + p.getName() + "Indices);");
+ }
+ _code.println();
+
+ //connect the network
+ for (Process p : x.getProcessList()) {
+ for (Port port : p.getPortList()) {
+ if (port.getName().equals(port.getBasename())) {
+ _code.printPrefixln(p.getName()
+ + "->_port" + port.getName() + "Fifo = &"
+ + port.getPeerResource().getName() + ";");
+ } else {
+ _code.printPrefix(p.getName()
+ + "->_port" + port.getBasename()
+ + "Fifo");
+ StringTokenizer tokenizer =
+ new StringTokenizer(port.getName().
+ replaceFirst(port.getBasename(), ""), "_");
+ while (tokenizer.hasMoreTokens()) {
+ _code.print("[" + tokenizer.nextToken()
+ + "]");
+ }
+ _code.println(" = &"
+ + port.getPeerResource().getName() + ";");
+ }
+ }
+ }
+ _code.println();
+
+ //initialize processes
+ for (Process p : x.getProcessList()) {
+ _code.printPrefixln(p.getName() + "->init();");
+ }
+ _code.println();
+
+ /*
+ _code.printPrefix("while(");
+ int counter = 0;
+ for (Process p : x.getProcessList()) {
+ if (counter > 0) {
+ _code.printPrefix(" ");
+ }
+ _code.print("!" + p.getName() + "->isDetached()");
+ if (counter++ < x.getProcessList().size() - 1) {
+ _code.println(" ||");
+ } else {
+ _code.println(")");
+ }
+ }
+ */
+ _code.printPrefixln("bool allBlocked = false;");
+ _code.printPrefixln("while(!allBlocked)");
+ _code.printLeftBracket();
+ _code.printPrefixln("allBlocked = true;");
+ for (Process p : x.getProcessList()) {
+ _code.printPrefixln("if (!" + p.getName()
+ + "->isDetached()) {");
+ //_code.printPrefixln(" " + p.getName() + "->fire();");
+ _code.printPrefixln(" if (" + p.getName()
+ + "->fire() == PT_ENDED) {");
+ _code.printPrefixln(" allBlocked = false;");
+ _code.printPrefixln(" }");
+ _code.printPrefixln("}");
+ }
+ _code.printRightBracket();
+ _code.println();
+
+ for (Process p : x.getProcessList()) {
+ _code.printPrefixln("delete " + p.getName() + ";");
+ }
+ _code.println();
+ _code.printPrefixln("return 0;");
+ _code.printRightBracket();
+ }
+ catch (Exception e) {
+ System.out.println("ProtothreadModuleVisitor: "
+ + "exception occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected CodePrintStream _code = null;
+ protected String _dir = null;
+}
+
--- /dev/null
+/* $Id: ProtothreadProcessVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.protothread;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.SourceCode;
+import dol.util.CodePrintStream;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class ProtothreadProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public ProtothreadProcessVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ Vector<String> processList = new Vector<String>();
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!processList.contains(basename)) {
+ processList.add(basename);
+ p.accept(this);
+ }
+ }
+ } catch (Exception e) {
+ System.out.println("Process Visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(Process p) {
+ try {
+ _createCppFile(p);
+ _createHeaderFile(p);
+ _adaptSources(p);
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ private void _createCppFile(Process p)
+ throws IOException {
+ String classname = p.getBasename() + "Wrapper";
+ String filename = _dir + _delimiter + classname + ".cpp";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ ps.printPrefixln("#include \"" + classname + ".h\"");
+ ps.printPrefixln("#include \"dolSupport.h\"");
+ ps.printPrefixln("#include <string.h>");
+ ps.println();
+ for (SourceCode sr : p.getSrcList()) {
+ ps.printPrefixln("#include \"" + "../processes/"
+ + sr.getLocality() + "\"");
+ }
+ ps.println();
+ ps.printPrefixln(classname + "::" + classname
+ + "(char* name, int iteratorIndex[4]) :");
+ ps.printPrefixln(" ProcessWrapper(name, iteratorIndex)");
+ ps.printLeftBracket();
+ //ps.printPrefixln("_state = new struct _local_states;");
+ //ps.printPrefixln("memcpy(_state, " + p.getBasename() + ".local, "
+ // + "sizeof(struct _local_states));");
+ //ps.printPrefixln("memcpy(&_process, &" + p.getBasename()
+ // + ", sizeof(DOLProcess));");
+ ps.printPrefixln("_state = (LocalState)new "
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State;");
+ ps.printPrefixln("_process.init = " + p.getBasename() + "_init;");
+ ps.printPrefixln("_process.fire = " + p.getBasename() + "_fire;");
+ ps.printPrefixln("_process.local = _state;");
+ ps.printPrefixln("_process.wptr = (void*)&_wrapper_data;");
+ ps.printPrefixln("_wrapper_data.wrapper = this;");
+ ps.printRightBracket();
+ ps.println();
+ ps.printPrefixln(classname + "::~" + classname + "()");
+ ps.printLeftBracket();
+ ps.printPrefixln("if (_state)");
+ ps.printPrefixln(" delete ("
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State*)_state;");
+ //ps.printPrefixln(" delete _state;");
+ ps.printRightBracket();
+ }
+
+ /**
+ *
+ */
+ private void _createHeaderFile(Process p)
+ throws IOException {
+ String classname = p.getBasename() + "Wrapper";
+ String filename = _dir + _delimiter + classname + ".h";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ ps.printPrefixln("#ifndef " + classname.toUpperCase()
+ + "_H");
+ ps.printPrefixln("#define " + classname.toUpperCase()
+ + "_H");
+ ps.println();
+ ps.printPrefixln("#include \"ProcessWrapper.h\"");
+ ps.printPrefixln("#include \"Fifo.h\"");
+ ps.printPrefixln("#include \"WindowedFifo.h\"");
+ ps.println();
+ ps.printPrefixln("class " + classname + ";");
+ ps.println();
+ ps.printPrefixln("typedef struct _" + p.getBasename()
+ + "_data {");
+ ps.printPrefixln(" int lc;");
+ ps.printPrefixln(" " + classname + " *wrapper;");
+ ps.printPrefixln("} " + p.getBasename() + "_data;");
+ ps.println();
+ ps.printPrefixln("class " + classname +
+ " : public ProcessWrapper");
+ ps.printLeftBracket();
+ ps.printPrefixln("public:");
+ ps.printPrefixln(" " + classname + "(char* name, "
+ + "int iteratorIndex[4]);");
+ ps.printPrefixln(" virtual ~" + classname + "();");
+ ps.println();
+
+ Vector<String> basenames = new Vector<String>();
+ for (Port port : p.getPortList()) {
+ if (!basenames.contains(port.getBasename())) {
+ basenames.add(port.getBasename());
+ } else {
+ continue;
+ }
+
+ Channel c = (Channel)port.getPeerResource();
+ if (port.getName().equals(port.getBasename())) {
+ if (c.getType().equals("fifo")) {
+ ps.printPrefixln(" Fifo* _port" + port.getName()
+ + "Fifo;");
+ } else if (c.getType().equals("wfifo")) {
+ ps.printPrefixln(" WindowedFifo* _port"
+ + port.getName() + "Fifo;");
+ }
+ } else {
+ if (c.getType().equals("fifo")) {
+ ps.printPrefix(" Fifo* _port"
+ + port.getBasename()
+ + "Fifo");
+ } else if (c.getType().equals("wfifo")) {
+ ps.printPrefix(" WindowedFifo* _port"
+ + port.getBasename()
+ + "Fifo");
+ }
+ StringTokenizer tokenizer =
+ new StringTokenizer(port.getRange(), ";");
+ while (tokenizer.hasMoreTokens()) {
+ ps.print("[" + tokenizer.nextToken()
+ + "]");
+ }
+ ps.println(";");
+ }
+ }
+ ps.println("");
+ ps.printPrefixln("protected:");
+ ps.printPrefixln(" struct _local_states *_state;");
+ ps.printPrefixln(" " + p.getBasename()
+ + "_data _wrapper_data;");
+ ps.printRightBracket();
+
+ ps.printPrefixln(";");
+ ps.println();
+ ps.printPrefixln("#endif");
+ }
+
+ /**
+ * Make modifications to source files of a process.
+ * Port names need to be strings for the SystemC code generation.
+ * Therefore, in the header files integer port names are put into
+ * quotation marks.
+ *
+ * @param p process whose sources should be adapted
+ * @throws IOException
+ */
+ protected void _adaptSources(Process p) throws IOException {
+ Sed sed = new Sed();
+ //modify header file
+ for (Port port : p.getPortList()) {
+ String processHeaderFile;
+
+ for (SourceCode sr : p.getSrcList()) {
+ processHeaderFile = _dir + _delimiter + ".."
+ + _delimiter + "processes" + _delimiter
+ + sr.getLocality().
+ replaceAll("(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ sed.sed(processHeaderFile,
+ "(#define[ ]+PORT_\\w*[ ]+)\"?"
+ + port.getBasename() + "\"?",
+ "$1 " + "static_cast<" + p.getBasename()
+ + "Wrapper *>((static_cast<" + p.getBasename()
+ + "_data *>(p->wptr))->wrapper)->_port"
+ + port.getBasename() + "Fifo");
+ }
+ }
+
+ //modify source file
+ for (SourceCode sr : p.getSrcList()) {
+ String processSourceFile = _dir + _delimiter + ".."
+ + _delimiter + "processes" + _delimiter
+ + sr.getLocality();
+
+ String line;
+ StringBuffer buffer = new StringBuffer();
+ FileInputStream fileInputStream = new FileInputStream(
+ processSourceFile);
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(fileInputStream));
+ while((line = reader.readLine()) != null) {
+ buffer.append(line + "\n");
+ }
+ reader.close();
+
+ String file = buffer.toString();
+ //insert PT_BEGIN() at beginning of fire() function
+ file = file.replaceAll(
+ "(int[ ]*" + p.getBasename()
+ + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)"
+ + "[\\s\\S&&[^\\{]]*)\\{",
+ "$1" + System.getProperty("line.separator") + "{"
+ + System.getProperty("line.separator") +
+ " PT_BEGIN((pt*)(p->wptr));");
+
+ //replace last return statement in fire function by PT_END()
+ //find beginning of fire function
+ Matcher matcher = Pattern.compile(
+ "(int[ ]*" + p.getBasename()
+ + "_fire[ ]*\\([ ]*DOLProcess[ ]*\\*p[ ]*\\)"
+ + "[\\s\\S&&[^\\{]]*)\\{").matcher(file);
+ matcher.find();
+ int i = 0;
+ try {
+ i = matcher.start();
+ } catch (Exception e) {
+ System.out.println("Error: could not find "
+ + p.getBasename() + "_fire() function in "
+ + processSourceFile + ".");
+ e.printStackTrace();
+ }
+ int openBraces = 0; //counter for open curly braces
+ //position of last return statement
+ int lastReturnStartPosition = 0;
+ int lastReturnEndPosition = 0;
+ while (i < file.length()) {
+ //ignore single-line comments
+ if (i < (file.length() - 1) &&
+ file.substring(i, i + 2).equals("//")) {
+ while (!file.substring(i, i + 1).equals("\n")) {
+ i++;
+ }
+ }
+ //ignore multi-line comments
+ else if (i < (file.length() - 1) &&
+ file.substring(i, i + 2).equals("/*")) {
+ while (!file.substring(i, i + 2).equals("*/")) {
+ i++;
+ }
+ }
+ //ignore strings
+ else if (file.substring(i, i + 1).equals("\"")) {
+ matcher = Pattern.compile("[\\s\\S&&[^\\\\]]\\\"").
+ matcher(file);
+ matcher.find(i + 1);
+ i = matcher.start() + 1;
+ }
+ else if (i < (file.length() - 5) &&
+ file.substring(i, i + 6).equals("return")) {
+ lastReturnStartPosition = i;
+ while (!file.substring(i, i + 1).equals(";")) {
+ i++;
+ }
+ lastReturnEndPosition = i;
+ } else if (file.substring(i, i + 1).equals("{")) {
+ openBraces++;
+ } else if (file.substring(i, i + 1).equals("}")) {
+ openBraces--;
+ if (openBraces == 0) {
+ break;
+ }
+ }
+ i++;
+ }
+
+ file = file.substring(0, lastReturnStartPosition) + "/* "
+ + file.substring(lastReturnStartPosition,
+ lastReturnEndPosition + 1)
+ + " (commented out by DOL) */"
+ + System.getProperty("line.separator")
+ + " PT_END((pt*)(p->wptr));"
+ + System.getProperty("line.separator")
+ + file.substring(lastReturnEndPosition + 2,
+ file.length());
+
+ BufferedWriter out = new BufferedWriter(new
+ FileWriter(processSourceFile));
+ out.write(file);
+ out.close();
+ }
+ }
+
+ protected String _dir = null;
+ CodePrintStream _wrapperHeader;
+}
--- /dev/null
+/* $Id: ProtothreadVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.protothread;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.Copier;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class ProtothreadVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public ProtothreadVisitor(String packageName) {
+ _packageName = packageName;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ _generateDirHierarchy();
+
+ x.accept(new ProtothreadMakefileVisitor(_srcDir));
+ x.accept(new ProtothreadModuleVisitor(_srcDir));
+ x.accept(new ProtothreadProcessVisitor(_wrapperDir));
+
+ } catch (Exception e) {
+ System.out.println(" SystemC PN Visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ *
+ */
+ private void _generateDirHierarchy()
+ throws IOException, FileNotFoundException {
+
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ _srcDir = _packageName + _delimiter + _srcDirName;
+ dir = new File(_srcDir);
+ dir.mkdirs();
+
+ _libDir = _srcDir + _delimiter + _libDirName;
+ dir = new File(_libDir);
+ dir.mkdirs();
+
+ _processDir = _srcDir + _delimiter + _processDirName;
+ dir = new File(_processDir);
+ dir.mkdirs();
+
+ _wrapperDir = _srcDir + _delimiter + _wrapperDirName;
+ dir = new File(_wrapperDir);
+ dir.mkdirs();
+
+ // copy library
+ String libraryPath = _ui.getMySystemCLib();
+ libraryPath = libraryPath.replaceAll("systemC",
+ "protothread");
+ File source = new File(libraryPath);
+ File destination = new File(_libDir);
+ new Copier().copy(source, destination);
+
+ //copy process src code
+ source = new File(_srcDirName);
+ destination = new File(_processDir);
+ new Copier().copy(source, destination);
+ }
+
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+
+ protected String _libDir = "";
+ protected static String _libDirName = "lib";
+
+ protected String _processDir = "";
+ protected static String _processDirName = "processes";
+
+ protected String _wrapperDir = "";
+ protected static String _wrapperDirName = "wrappers";
+}
+
--- /dev/null
+#include "Fifo.h"\r
+\r
+/**\r
+ *\r
+ */\r
+Fifo::Fifo(unsigned size = 18) {\r
+ //std::cout << "Create Fifo." << std::endl;\r
+ _size = size;\r
+ _buffer = new char[_size];\r
+ _use = 0; \r
+ _tail = 0;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+Fifo::~Fifo() {\r
+ //std::cout << "Delete Fifo." << std::endl;\r
+ if (_buffer) {\r
+ delete _buffer;\r
+ }\r
+ _buffer = 0;\r
+ _use = 0; \r
+ _tail = 0;\r
+ //std::cout << "Deleted Fifo." << std::endl;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::read(void *destination, unsigned len) {\r
+ char* buffer = (char*)destination;\r
+ unsigned read = (len <= _use ? len : 0);\r
+ //std::cout << "Try to read " << len << " bytes from Fifo." << std::endl;\r
+\r
+ if (_tail + read <= _size) {\r
+ memcpy(buffer, _buffer + _tail, read);\r
+ }\r
+ else {\r
+ memcpy(buffer, _buffer + _tail, _size - _tail);\r
+ memcpy(buffer + _size - _tail, _buffer, read - _size + _tail);\r
+ }\r
+\r
+ _tail = (_tail + read) % _size;\r
+ _use -= read;\r
+ //std::cout << "Read " << read << " bytes from Fifo." << std::endl;\r
+ return read;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::write(const void *source, unsigned len) {\r
+ char* buffer = (char*)source;\r
+ unsigned write = (len <= unused() ? len : 0);\r
+ unsigned head = (_tail + _use) % _size;\r
+ //std::cout << "Try to write " << len << " bytes to Fifo." << std::endl;\r
+\r
+ if (head + write <= _size) {\r
+ memcpy(_buffer + head, buffer, write);\r
+ }\r
+ else {\r
+ memcpy(_buffer + head, buffer, _size - head);\r
+ memcpy(_buffer, buffer + _size - head, write - _size + head);\r
+ }\r
+\r
+ _use += write;\r
+ //std::cout << "Wrote " << write << " bytes to Fifo." << std::endl;\r
+ return write;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::size() const {\r
+ return (_size);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::unused() const {\r
+ return (_size) - _use;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned Fifo::used() const {\r
+ return _use; \r
+}\r
+\r
+/**\r
+ * Test the implementation\r
+ */\r
+/*\r
+int main() {\r
+ std::cout.width(5);\r
+ Fifo *myFifo = new Fifo();\r
+ for (int j = 0; j < 3; j++) {\r
+ for (int i = 0; i < 6; i++) {\r
+ std::cout << "write " << i << " to Fifo. ";\r
+ int write = myFifo->write(&i, sizeof(int));\r
+ printf(" %d ", write);\r
+ if (write == sizeof(int)) {\r
+ std::cout << "used: " << std::setw(2) << myFifo->used()\r
+ << ", unused: " << std::setw(2) << myFifo->unused()\r
+ << ", size: " << std::setw(2) << myFifo->size()\r
+ << std::endl;\r
+ } else {\r
+ std::cout << std::endl;\r
+ }\r
+ }\r
+ for (int i = 0; i < 6; i++) {\r
+ int value;\r
+ int read = myFifo->read(&value, sizeof(int));\r
+ printf(" %d ", read);\r
+ if (read == sizeof(int)) {\r
+ std::cout << "read " << value << " from Fifo ";\r
+ std::cout << "used: " << std::setw(2) << myFifo->used()\r
+ << ", unused: " << std::setw(2) << myFifo->unused()\r
+ << ", size: " << std::setw(2) << myFifo->size()\r
+ << std::endl;\r
+ }\r
+ }\r
+ }\r
+ delete myFifo;\r
+ return 0;\r
+}\r
+*/\r
--- /dev/null
+#ifndef _FIFO_H_\r
+#define _FIFO_H_\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+class Fifo {\r
+ public:\r
+ Fifo(unsigned size);\r
+ virtual ~Fifo();\r
+\r
+ virtual unsigned read(void *destination, unsigned len);\r
+ virtual unsigned write(const void *source, unsigned len);\r
+ virtual unsigned used() const;\r
+ virtual unsigned unused() const;\r
+ virtual unsigned size() const;\r
+\r
+ protected:\r
+ char *_buffer;\r
+ unsigned _use;\r
+ unsigned _tail;\r
+ unsigned _size;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#include "ProcessWrapper.h"
+
+/**
+ *
+ */
+ProcessWrapper::ProcessWrapper(char* name, int iteratorIndex[4]) {
+ //copy name, deliberately avoid using strlen and strcpy for code size
+ //minimization
+ int nameLength = 0;
+ while (name[nameLength] != 0) {
+ nameLength++;
+ }
+ _name = new char[nameLength + 1];
+ for (int i = 0; i < nameLength; i++) {
+ _name[i] = name[i];
+ }
+
+ /*
+ _name = new char[strlen(name) + 1];
+ strcpy(_name, name);
+ */
+
+ _isDetached = false;
+ for (int i = 0; i < 4; i++) {
+ _iteratorIndex[i] = iteratorIndex[i];
+ }
+}
+
+/**
+ *
+ */
+ProcessWrapper::~ProcessWrapper() {
+ if (_name) {
+ delete _name;
+ }
+}
+
+/**
+ *
+ */
+void ProcessWrapper::init() {
+ _process.init(&_process);
+}
+
+/**
+ *
+ */
+int ProcessWrapper::fire() {
+ return _process.fire(&_process);
+}
+
+/**
+ *
+ */
+void ProcessWrapper::detach() {
+ _isDetached = true;
+}
+
+/**
+ * Get the index of this process.
+ * @param indexNumber position of index (starting at 0)
+ */
+int ProcessWrapper::getIndex(unsigned indexNumber) const {
+ if (indexNumber < 4) {
+ return _iteratorIndex[indexNumber];
+ }
+ return -1;
+}
--- /dev/null
+#ifndef _PROCESSWRAPPER_H_
+#define _PROCESSWRAPPER_H_
+
+#include <dol.h>
+
+class ProcessWrapper
+{
+ public:
+ ProcessWrapper(char* name, int iteratorIndex[4]);
+ virtual ~ProcessWrapper();
+
+ virtual void init();
+ virtual int fire();
+ virtual bool isDetached() { return _isDetached; }
+ virtual void detach();
+ virtual int getIndex(unsigned indexNumber) const;
+
+ protected:
+ char* _name;;
+ DOLProcess _process;
+ bool _isDetached;
+ int _iteratorIndex[4];
+};
+
+#endif
--- /dev/null
+#include "WindowedFifo.h"\r
+\r
+/**\r
+ *\r
+ */\r
+WindowedFifo::WindowedFifo(unsigned size = 20) {\r
+ //std::cout << "Create WindowedFifo." << std::endl;\r
+ _size = size;\r
+ _buffer = new char[_size];\r
+ _head = 0;\r
+ _tail = 0;\r
+ _headRoom = 0;\r
+ _tailRoom = 0;\r
+ _use = 0;\r
+ //indicates whether Fifo is empty or full if _head == _tail\r
+ //_isFull = false;\r
+ _isHeadReserved = false;\r
+ _isTailReserved = false;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+WindowedFifo::~WindowedFifo() {\r
+ //std::cout << "Delete WindowedFifo." << std::endl;\r
+ if (_buffer) {\r
+ delete _buffer;\r
+ }\r
+ _buffer = 0;\r
+ _head = 0;\r
+ _tail = 0;\r
+ _use = 0;\r
+ //std::cout << "Deleted WindowedFifo." << std::endl;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::reserve(void** dest, unsigned len) {\r
+ char** destination = (char**)dest;\r
+ //std::cout << "Attempt to reserve " << len << " bytes." << std::endl;\r
+\r
+ //can only reserve once piece at a time\r
+ if (_isHeadReserved) {\r
+ *destination = 0;\r
+ return 0;\r
+ }\r
+\r
+ //reserve at most as much memory as still available in the buffer\r
+ unsigned write = (len <= _size - _use ? len : _size - _use);\r
+\r
+ if (write > 0) {\r
+ //if wrap-around in buffer: return only buffer for the\r
+ //contiguous buffer space\r
+ if (_head + write > _size) {\r
+ write = _size - _head;\r
+ }\r
+\r
+ _headRoom = (_head + write) == _size? 0 : _head + write;\r
+ *destination = &(_buffer[_head]);\r
+ _isHeadReserved = true;\r
+ }\r
+\r
+ //std::cout << "Reserved " << write << " bytes." << std::endl;\r
+ _writeReserve = write; \r
+ return write;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void WindowedFifo::release() {\r
+ if (_isHeadReserved) {\r
+ //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl;\r
+ _head = _headRoom;\r
+ _use += _writeReserve;\r
+ _isHeadReserved = false;\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::capture(void **dest, unsigned len) {\r
+ char** destination = (char**)dest;\r
+ //std::cout << "Attempt to capture " << len << " bytes." << std::endl;\r
+\r
+ if (_isTailReserved) {\r
+ //std::cout << "Only one attempt to capture allowed." << std::endl;\r
+ *destination = 0;\r
+ return 0;\r
+ }\r
+\r
+ //capture at most as much data as available in the buffer\r
+ unsigned read = (len <= _use ? len : _use);\r
+\r
+ if (read > 0) {\r
+ //if wrap-around in buffer: return only buffer for the\r
+ //conntiguous buffer space\r
+ if (_tail + read> _size) {\r
+ read = _size - _tail;\r
+ }\r
+\r
+ _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read;\r
+ *destination = &(_buffer[_tail]);\r
+ _isTailReserved = true;\r
+ }\r
+\r
+ //std::cout << "Captured " << read << " bytes." << std::endl;\r
+\r
+ _readReserve = read; \r
+ return read;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void WindowedFifo::consume() {\r
+ if (_isTailReserved) {\r
+ //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl;\r
+ _tail = _tailRoom;\r
+ _use -= _readReserve;\r
+ _isTailReserved = false;\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::size() const {\r
+ return _size;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::unused() const {\r
+ return _size - _use;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned WindowedFifo::used() const {\r
+ return _use;\r
+}\r
+\r
+/**\r
+ * Test the implementation\r
+ */\r
+/*\r
+#include <iostream>\r
+#include <iomanip>\r
+using namespace std;\r
+\r
+int main() {\r
+ WindowedFifo *myFifo = new WindowedFifo(16);\r
+\r
+ int* buf1;\r
+ int* buf2;\r
+ int x = myFifo->reserve((void**)&buf1, 8);\r
+ *buf1 = 10;\r
+ *(buf1 + 1) = 20;\r
+ myFifo->release();\r
+ int y = myFifo->capture((void**)&buf2, 8);\r
+ std::cout << "read " << *buf2 << " " << *(buf2 + 1) << std::endl;\r
+ myFifo->consume();\r
+\r
+ for (int j = 0; j < 3; j++) {\r
+ for (int i = 0; i < 6; i++) {\r
+ std::cout << "write " << i << " to Fifo. ";\r
+ int write = myFifo->reserve((void**)&buf1, sizeof(int));\r
+ if (write == sizeof(int)) {\r
+ *buf1 = i;\r
+ myFifo->release();\r
+ std::cout << "used: " << std::setw(2) << myFifo->used()\r
+ << ", unused: " << std::setw(2) << myFifo->unused()\r
+ << ", size: " << std::setw(2) << myFifo->size()\r
+ << std::endl;\r
+ } else {\r
+ std::cout << std::endl;\r
+ }\r
+ }\r
+ for (int i = 0; i < 16; i++) {\r
+ char* buf3;\r
+ int read = myFifo->capture((void**)&buf3, sizeof(char));\r
+ if (read == sizeof(char)) {\r
+ std::cout << "read " << (unsigned)*buf3 << " from Fifo ";\r
+ std::cout << "used: " << std::setw(2) << myFifo->used()\r
+ << ", unused: " << std::setw(2) << myFifo->unused()\r
+ << ", size: " << std::setw(2) << myFifo->size()\r
+ << std::endl;\r
+ myFifo->consume();\r
+ } else {\r
+ std::cout << "read nothing from Fifo." << std::endl;\r
+ }\r
+\r
+ }\r
+ }\r
+ delete myFifo;\r
+ return 0;\r
+}\r
+*/\r
--- /dev/null
+#ifndef _WINDOWEDFIFO_H_\r
+#define _WINDOWEDFIFO_H_\r
+\r
+class WindowedFifo {\r
+ public:\r
+ WindowedFifo(unsigned size);\r
+ virtual ~WindowedFifo();\r
+\r
+ virtual unsigned reserve(void** destination, unsigned len);\r
+ virtual void release();\r
+\r
+ virtual unsigned capture(void** destination, unsigned len);\r
+ virtual void consume();\r
+\r
+ virtual unsigned used() const;\r
+ virtual unsigned unused() const;\r
+ virtual unsigned size() const;\r
+ protected:\r
+ char *_buffer;\r
+ unsigned _head;\r
+ unsigned _tail;\r
+ unsigned _headRoom;\r
+ unsigned _tailRoom;\r
+ unsigned _size;\r
+ unsigned _use; \r
+ unsigned _writeReserve;
+ unsigned _readReserve;
+ bool _isHeadReserved;\r
+ bool _isTailReserved;\r
+};\r
+\r
+#endif\r
--- /dev/null
+#ifndef DOL_H
+#define DOL_H
+
+/************************************************************************
+ * do not add code to this header
+ ************************************************************************/
+
+/**
+ * Define the DOL process handler scheme.
+ * - Local variables are defined in structure LocalState. Local
+ * variables may vary from different processes.
+ * - The ProcessInit function pointer points to a function which
+ * initializes a process.
+ * - The ProcessFire function pointer points to a function which
+ * performs the actual computation. The communication between
+ * processes is inside the ProcessFire function.
+ * - The WPTR is a placeholder for callback. One can just
+ * leave it blank.
+ */
+
+//structure for local memory of process
+typedef struct _local_states *LocalState;
+
+//additional behavioral functions could be declared here
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+//process handler
+struct _process;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr; //placeholder for wrapper instance
+} DOLProcess;
+
+#endif
--- /dev/null
+#include "dolSupport.h"\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned read(void* fifo, void* buf, unsigned len, DOLProcess* p) {\r
+ return ((Fifo*)fifo)->read(buf, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned write(void* fifo, void* buf, unsigned len, DOLProcess* p) {\r
+ return ((Fifo*)fifo)->write(buf, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned reserve(void* fifo, void** destination, unsigned len, DOLProcess* p) {\r
+ return ((WindowedFifo*)fifo)->reserve(destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void release(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*)fifo)->release();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned capture(void* fifo, void** destination, unsigned len, DOLProcess* p) {\r
+ return ((WindowedFifo*)fifo)->capture(destination, len);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void consume(void* fifo, DOLProcess* p) {\r
+ ((WindowedFifo*)fifo)->consume();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void DOL_detach(DOLProcess* p) {\r
+ static_cast<ProcessWrapper *>((static_cast<process_data *>(p->wptr))->wrapper)->detach();\r
+}\r
+\r
+\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0) {\r
+ *port = (void**)((void**)base)[index0];\r
+}\r
+\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1) {\r
+ *port = (void**)((void**)base)[index0 * range1 + index1];\r
+}\r
+\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2) {\r
+ *port = (void**)((void**)base)[index0 * range1 * range2\r
+ + index1 * range2 + index2];\r
+}\r
+\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2,\r
+ int index3, int range3) {\r
+ *port = (void**)((void**)base)[index0 * range1 * range2 * range3\r
+ + index1 * range2 * range3\r
+ + index2 * range3\r
+ + index3];\r
+}\r
--- /dev/null
+#ifndef DOLSUPPORT_H\r
+#define DOLSUPPORT_H\r
+\r
+#include "dol.h"\r
+#include "ProcessWrapper.h"\r
+#include "Fifo.h"\r
+#include "WindowedFifo.h"\r
+#include "pt.h"\r
+\r
+typedef struct _process_data {\r
+ int lc;\r
+ ProcessWrapper *wrapper;\r
+} process_data;\r
+\r
+\r
+#define DOL_read(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), read(port, buf, size, process) == size);\r
+\r
+#define DOL_write(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), write(port, buf, size, process) == size);\r
+\r
+#define DOL_reserve(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), reserve(port, (void**)buf, size, process) == size);\r
+\r
+#define DOL_release(port, process) \\r
+ release(port, process);\r
+\r
+#define DOL_capture(port, buf, size, process) \\r
+ PT_WAIT_UNTIL((pt*)(p->wptr), capture(port, (void**)buf, size, process) == size);\r
+\r
+#define DOL_consume(port, process) \\r
+ consume(port, process);\r
+\r
+void DOL_detach(DOLProcess* p);\r
+\r
+//macros to deal with iterated ports\r
+/**\r
+ * macro to create a variable to store a port name\r
+ *\r
+ * @param name name of the variable\r
+ */\r
+#define CREATEPORTVAR(name) static Fifo *name\r
+\r
+/**\r
+ * Create the port name of an iterated port based on its basename and the\r
+ * given indices.\r
+ *\r
+ * @param port buffer where the result is stored (created using\r
+ * CREATEPORTVAR)\r
+ * @param base basename of the port\r
+ * @param number_of_indices number of dimensions of the port\r
+ * @param index_range_pairs index and range values for each dimension\r
+ */\r
+\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+ createPort((void**)(&port), base, number_of_indices, index_range_pairs)\r
+\r
+#define GETINDEX(dimension) \\r
+ static_cast<ProcessWrapper *>((static_cast<process_data *>(p->wptr))->wrapper)->getIndex(dimension)\r
+\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1, int index2, int range2);\r
+void createPort(void** port, void* base, int number_of_indices, int index0, int range0, int index1, int range1, int index2, int range2, int index3, int range3);\r
+\r
+//fifo access functions\r
+unsigned write(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+unsigned read(void* fifo, void* buf, unsigned len, DOLProcess* p);\r
+\r
+//windowed fifo access functions\r
+unsigned reserve(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+void release(void* fifo, DOLProcess* p);\r
+unsigned capture(void* fifo, void** destination, unsigned len, DOLProcess* p);\r
+void consume(void* fifo, DOLProcess* p);\r
+\r
+#endif\r
--- /dev/null
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-addrlabels.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on the "Labels as
+ * values" feature of gcc
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations is based on a special
+ * feature of the GCC C compiler called "labels as values". This
+ * feature allows assigning pointers with the address of the code
+ * corresponding to a particular C label.
+ *
+ * For more information, see the GCC documentation:
+ * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+ *
+ */
+
+#ifndef __LC_ADDRLABELS_H__
+#define __LC_ADDRLABELS_H__
+
+/** \hideinitializer */
+typedef void * lc_t;
+
+#define LC_INIT(s) s = NULL
+
+#define LC_RESUME(s) \
+ do { \
+ if(s != NULL) { \
+ goto *s; \
+ } \
+ } while(0)
+
+#define LC_CONCAT2(s1, s2) s1##s2
+#define LC_CONCAT(s1, s2) LC_CONCAT2(s1, s2)
+
+#define LC_SET(s) \
+ do { \
+ LC_CONCAT(LC_LABEL, __LINE__): \
+ (s) = &&LC_CONCAT(LC_LABEL, __LINE__); \
+ } while(0)
+
+#define LC_END(s)
+
+#endif /* __LC_ADDRLABELS_H__ */
+/** @} */
--- /dev/null
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-switch.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on switch() statment
+ * \author Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations uses the C switch()
+ * statement to resume execution of a function somewhere inside the
+ * function's body. The implementation is based on the fact that
+ * switch() statements are able to jump directly into the bodies of
+ * control structures such as if() or while() statmenets.
+ *
+ * This implementation borrows heavily from Simon Tatham's coroutines
+ * implementation in C:
+ * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+ */
+
+#ifndef __LC_SWITCH_H__
+#define __LC_SWITCH_H__
+
+/* WARNING! lc implementation using switch() does not work if an
+ LC_SET() is done within another switch() statement! */
+
+/** \hideinitializer */
+typedef unsigned short lc_t;
+
+#define LC_INIT(s) s = 0;
+
+#define LC_RESUME(s) switch(s) { case 0:
+
+#define LC_SET(s) s = __LINE__; case __LINE__:
+
+#define LC_END(s) }
+
+#endif /* __LC_SWITCH_H__ */
+
+/** @} */
--- /dev/null
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \defgroup lc Local continuations
+ * @{
+ *
+ * Local continuations form the basis for implementing protothreads. A
+ * local continuation can be <i>set</i> in a specific function to
+ * capture the state of the function. After a local continuation has
+ * been set can be <i>resumed</i> in order to restore the state of the
+ * function at the point where the local continuation was set.
+ *
+ *
+ */
+
+/**
+ * \file lc.h
+ * Local continuations
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifdef DOXYGEN
+/**
+ * Initialize a local continuation.
+ *
+ * This operation initializes the local continuation, thereby
+ * unsetting any previously set continuation state.
+ *
+ * \hideinitializer
+ */
+#define LC_INIT(lc)
+
+/**
+ * Set a local continuation.
+ *
+ * The set operation saves the state of the function at the point
+ * where the operation is executed. As far as the set operation is
+ * concerned, the state of the function does <b>not</b> include the
+ * call-stack or local (automatic) variables, but only the program
+ * counter and such CPU registers that needs to be saved.
+ *
+ * \hideinitializer
+ */
+#define LC_SET(lc)
+
+/**
+ * Resume a local continuation.
+ *
+ * The resume operation resumes a previously set local continuation, thus
+ * restoring the state in which the function was when the local
+ * continuation was set. If the local continuation has not been
+ * previously set, the resume operation does nothing.
+ *
+ * \hideinitializer
+ */
+#define LC_RESUME(lc)
+
+/**
+ * Mark the end of local continuation usage.
+ *
+ * The end operation signifies that local continuations should not be
+ * used any more in the function. This operation is not needed for
+ * most implementations of local continuation, but is required by a
+ * few implementations.
+ *
+ * \hideinitializer
+ */
+#define LC_END(lc)
+
+/**
+ * \var typedef lc_t;
+ *
+ * The local continuation type.
+ *
+ * \hideinitializer
+ */
+#endif /* DOXYGEN */
+
+#ifndef __LC_H__
+#define __LC_H__
+
+
+#ifdef LC_INCLUDE
+#include LC_INCLUDE
+#else
+#include "lc-switch.h"
+#endif /* LC_INCLUDE */
+
+#endif /* __LC_H__ */
+
+/** @} */
+/** @} */
--- /dev/null
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: pt-sem.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \defgroup ptsem Protothread semaphores
+ * @{
+ *
+ * This module implements counting semaphores on top of
+ * protothreads. Semaphores are a synchronization primitive that
+ * provide two operations: "wait" and "signal". The "wait" operation
+ * checks the semaphore counter and blocks the thread if the counter
+ * is zero. The "signal" operation increases the semaphore counter but
+ * does not block. If another thread has blocked waiting for the
+ * semaphore that is signalled, the blocked thread will become
+ * runnable again.
+ *
+ * Semaphores can be used to implement other, more structured,
+ * synchronization primitives such as monitors and message
+ * queues/bounded buffers (see below).
+ *
+ * The following example shows how the producer-consumer problem, also
+ * known as the bounded buffer problem, can be solved using
+ * protothreads and semaphores. Notes on the program follow after the
+ * example.
+ *
+ \code
+#include "pt-sem.h"
+
+#define NUM_ITEMS 32
+#define BUFSIZE 8
+
+static struct pt_sem mutex, full, empty;
+
+PT_THREAD(producer(struct pt *pt))
+{
+ static int produced;
+
+ PT_BEGIN(pt);
+
+ for(produced = 0; produced < NUM_ITEMS; ++produced) {
+
+ PT_SEM_WAIT(pt, &full);
+
+ PT_SEM_WAIT(pt, &mutex);
+ add_to_buffer(produce_item());
+ PT_SEM_SIGNAL(pt, &mutex);
+
+ PT_SEM_SIGNAL(pt, &empty);
+ }
+
+ PT_END(pt);
+}
+
+PT_THREAD(consumer(struct pt *pt))
+{
+ static int consumed;
+
+ PT_BEGIN(pt);
+
+ for(consumed = 0; consumed < NUM_ITEMS; ++consumed) {
+
+ PT_SEM_WAIT(pt, &empty);
+
+ PT_SEM_WAIT(pt, &mutex);
+ consume_item(get_from_buffer());
+ PT_SEM_SIGNAL(pt, &mutex);
+
+ PT_SEM_SIGNAL(pt, &full);
+ }
+
+ PT_END(pt);
+}
+
+PT_THREAD(driver_thread(struct pt *pt))
+{
+ static struct pt pt_producer, pt_consumer;
+
+ PT_BEGIN(pt);
+
+ PT_SEM_INIT(&empty, 0);
+ PT_SEM_INIT(&full, BUFSIZE);
+ PT_SEM_INIT(&mutex, 1);
+
+ PT_INIT(&pt_producer);
+ PT_INIT(&pt_consumer);
+
+ PT_WAIT_THREAD(pt, producer(&pt_producer) &
+ consumer(&pt_consumer));
+
+ PT_END(pt);
+}
+ \endcode
+ *
+ * The program uses three protothreads: one protothread that
+ * implements the consumer, one thread that implements the producer,
+ * and one protothread that drives the two other protothreads. The
+ * program uses three semaphores: "full", "empty" and "mutex". The
+ * "mutex" semaphore is used to provide mutual exclusion for the
+ * buffer, the "empty" semaphore is used to block the consumer is the
+ * buffer is empty, and the "full" semaphore is used to block the
+ * producer is the buffer is full.
+ *
+ * The "driver_thread" holds two protothread state variables,
+ * "pt_producer" and "pt_consumer". It is important to note that both
+ * these variables are declared as <i>static</i>. If the static
+ * keyword is not used, both variables are stored on the stack. Since
+ * protothreads do not store the stack, these variables may be
+ * overwritten during a protothread wait operation. Similarly, both
+ * the "consumer" and "producer" protothreads declare their local
+ * variables as static, to avoid them being stored on the stack.
+ *
+ *
+ */
+
+/**
+ * \file
+ * Couting semaphores implemented on protothreads
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PT_SEM_H__
+#define __PT_SEM_H__
+
+#include "pt.h"
+
+struct pt_sem {
+ unsigned int count;
+};
+
+/**
+ * Initialize a semaphore
+ *
+ * This macro initializes a semaphore with a value for the
+ * counter. Internally, the semaphores use an "unsigned int" to
+ * represent the counter, and therefore the "count" argument should be
+ * within range of an unsigned int.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \param c (unsigned int) The initial count of the semaphore.
+ * \hideinitializer
+ */
+#define PT_SEM_INIT(s, c) (s)->count = c
+
+/**
+ * Wait for a semaphore
+ *
+ * This macro carries out the "wait" operation on the semaphore. The
+ * wait operation causes the protothread to block while the counter is
+ * zero. When the counter reaches a value larger than zero, the
+ * protothread will continue.
+ *
+ * \param pt (struct pt *) A pointer to the protothread (struct pt) in
+ * which the operation is executed.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \hideinitializer
+ */
+#define PT_SEM_WAIT(pt, s) \
+ do { \
+ PT_WAIT_UNTIL(pt, (s)->count > 0); \
+ --(s)->count; \
+ } while(0)
+
+/**
+ * Signal a semaphore
+ *
+ * This macro carries out the "signal" operation on the semaphore. The
+ * signal operation increments the counter inside the semaphore, which
+ * eventually will cause waiting protothreads to continue executing.
+ *
+ * \param pt (struct pt *) A pointer to the protothread (struct pt) in
+ * which the operation is executed.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \hideinitializer
+ */
+#define PT_SEM_SIGNAL(pt, s) ++(s)->count
+
+#endif /* __PT_SEM_H__ */
+
+/** @} */
+/** @} */
+
--- /dev/null
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: pt.h 1 2010-02-24 13:03:05Z haidw $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \file
+ * Protothreads implementation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PT_H__
+#define __PT_H__
+
+#include "lc.h"
+
+typedef struct _pt {
+ lc_t lc;
+} pt;
+
+#define PT_WAITING 0
+#define PT_YIELDED 1
+#define PT_EXITED 2
+#define PT_ENDED 3
+
+/**
+ * \name Initialization
+ * @{
+ */
+
+/**
+ * Initialize a protothread.
+ *
+ * Initializes a protothread. Initialization must be done prior to
+ * starting to execute the protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_INIT(pt) LC_INIT((pt)->lc)
+
+/** @} */
+
+/**
+ * \name Declaration and definition
+ * @{
+ */
+
+/**
+ * Declaration of a protothread.
+ *
+ * This macro is used to declare a protothread. All protothreads must
+ * be declared with this macro.
+ *
+ * \param name_args The name and arguments of the C function
+ * implementing the protothread.
+ *
+ * \hideinitializer
+ */
+#define PT_THREAD(name_args) char name_args
+
+/**
+ * Declare the start of a protothread inside the C function
+ * implementing the protothread.
+ *
+ * This macro is used to declare the starting point of a
+ * protothread. It should be placed at the start of the function in
+ * which the protothread runs. All C statements above the PT_BEGIN()
+ * invokation will be executed each time the protothread is scheduled.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
+
+/**
+ * Declare the end of a protothread.
+ *
+ * This macro is used for declaring that a protothread ends. It must
+ * always be used together with a matching PT_BEGIN() macro.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
+ PT_INIT(pt); return PT_ENDED; }
+
+/** @} */
+
+/**
+ * \name Blocked wait
+ * @{
+ */
+
+/**
+ * Block and wait until condition is true.
+ *
+ * This macro blocks the protothread until the specified condition is
+ * true.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param condition The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_UNTIL(pt, condition) \
+ do { \
+ LC_SET((pt)->lc); \
+ if(!(condition)) { \
+ return PT_WAITING; \
+ } \
+ } while(0)
+
+/**
+ * Block and wait while condition is true.
+ *
+ * This function blocks and waits while condition is true. See
+ * PT_WAIT_UNTIL().
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
+
+/** @} */
+
+/**
+ * \name Hierarchical protothreads
+ * @{
+ */
+
+/**
+ * Block and wait until a child protothread completes.
+ *
+ * This macro schedules a child protothread. The current protothread
+ * will block until the child protothread completes.
+ *
+ * \note The child protothread must be manually initialized with the
+ * PT_INIT() function before this function is used.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
+
+/**
+ * Spawn a child protothread and wait until it exits.
+ *
+ * This macro spawns a child protothread and waits until it exits. The
+ * macro can only be used within a protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param child A pointer to the child protothread's control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \hideinitializer
+ */
+#define PT_SPAWN(pt, child, thread) \
+ do { \
+ PT_INIT((child)); \
+ PT_WAIT_THREAD((pt), (thread)); \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Exiting and restarting
+ * @{
+ */
+
+/**
+ * Restart the protothread.
+ *
+ * This macro will block and cause the running protothread to restart
+ * its execution at the place of the PT_BEGIN() call.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_RESTART(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_WAITING; \
+ } while(0)
+
+/**
+ * Exit the protothread.
+ *
+ * This macro causes the protothread to exit. If the protothread was
+ * spawned by another protothread, the parent protothread will become
+ * unblocked and can continue to run.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_EXIT(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_EXITED; \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Calling a protothread
+ * @{
+ */
+
+/**
+ * Schedule a protothread.
+ *
+ * This function shedules a protothread. The return value of the
+ * function is non-zero if the protothread is running or zero if the
+ * protothread has exited.
+ *
+ * \param f The call to the C function implementing the protothread to
+ * be scheduled
+ *
+ * \hideinitializer
+ */
+#define PT_SCHEDULE(f) ((f) < PT_EXITED)
+
+/** @} */
+
+/**
+ * \name Yielding from a protothread
+ * @{
+ */
+
+/**
+ * Yield from the current protothread.
+ *
+ * This function will yield the protothread, thereby allowing other
+ * processing to take place in the system.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD(pt) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if(PT_YIELD_FLAG == 0) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/**
+ * \brief Yield from the protothread until a condition occurs.
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * This function will yield the protothread, until the
+ * specified condition evaluates to true.
+ *
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD_UNTIL(pt, cond) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if((PT_YIELD_FLAG == 0) || !(cond)) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/** @} */
+
+#endif /* __PT_H__ */
+
+/** @} */
--- /dev/null
+/* $Id: RtemsMakefileVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.rtems;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.Configuration;
+import dol.main.UserInterface;
+import dol.parser.xml.archischema.ArchiXmlParser;
+import dol.parser.xml.mapschema.MapXmlParser;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a RTEMS package Makefile.
+ */
+public class RtemsMakefileVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of the Makefile
+ */
+ public RtemsMakefileVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ * Create a Makefile for the given process network.
+ *
+ * @param pn process network
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ String filename = _dir + _delimiter + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ _ui = UserInterface.getInstance();
+ if (_ui.getRtemsBSP().equals("pc386")) {
+ ps.println(getPc386Makefile(pn));
+ } else if (_ui.getRtemsBSP().equals("mparm")) {
+ ps.println(getMparmMakefile(pn));
+ }
+ } catch (Exception e) {
+ System.out.println("RtemsMakefileVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Create a makefile for the pc386 board support package.
+ *
+ * @param pn process network
+ * @return makefile for pc386 board support package
+ */
+ protected String getMparmMakefile(ProcessNetwork pn) {
+ String makefile = "";
+ String newline = System.getProperty("line.separator");
+ makefile += "ifndef SWARMDIR" + newline;
+ makefile += " $(error Fatal error: Undefined SWARMDIR "
+ + "environment variable!)" + newline;
+ makefile += "endif" + newline;
+ makefile += "" + newline;
+ makefile += "ifndef RTEMS_MAKEFILE_PATH" + newline;
+ makefile += " $(error Fatal error: Undefined "
+ + "RTEMS_MAKEFILE_PATH environment variable!)" + newline;
+ makefile += "endif" + newline;
+ makefile += "" + newline;
+ makefile += "ifdef EXENAME" + newline;
+ makefile += " EXEC=$(EXENAME).exe" + newline;
+ makefile += "else" + newline;
+ makefile += " EXEC=app.exe" + newline;
+ makefile += "endif" + newline;
+ makefile += "" + newline;
+ makefile += "PGM=${ARCH}/$(EXEC)" + newline;
+ makefile += "" + newline;
+ makefile += "# optional managers required" + newline;
+ makefile += "MANAGERS=io mp msg signal event region partition";
+ makefile += newline + newline;
+
+ if (_ui.getRtemsBSP().equals("mparm")) {
+ makefile += "# scratchpad queue lib" + newline;
+ makefile += "QUEUELIB=que_lib/lib" + newline;
+ makefile += "SS_SEMAPHORE_LIB_PATH = "
+ + "${QUEUELIB}/ss_semaphore_lib" + newline;
+ makefile +="SCRATCH_QUEUE_LIB_PATH = "
+ + "${QUEUELIB}/scratch_queue_lib" + newline;
+ makefile += "SCRATCH_SEMAPHORE_LIB_PATH = "
+ + "${QUEUELIB}/scratch_semaphore_lib" + newline;
+ makefile += "EXT_INT_LIB_PATH = ${QUEUELIB}/ext_int_lib" + newline;
+ }
+
+ makefile += "" + newline;
+ makefile += "#H_files" + newline;
+ makefile += "H_FILES=buffer_test_io.h" + newline;
+
+ if (_ui.getRtemsBSP().equals("mparm")) {
+ makefile += "H_FILES += system.h tmacros.h" + newline;
+ makefile += newline;
+ makefile += "COMMON_FLAGS += -DMPARM" + newline;
+ makefile += "COMMON_FLAGS += -I$(QUEUELIB)" + newline;
+ makefile += "COMMON_FLAGS += -I$(SS_SEMAPHORE_LIB_PATH)"
+ + newline;
+ makefile += "COMMON_FLAGS += -I$(SCRATCH_QUEUE_LIB_PATH)"
+ + newline;
+ makefile += "COMMON_FLAGS += -I$(SCRATCH_SEMAPHORE_LIB_PATH)";
+ makefile += newline;
+ makefile += newline;
+ makefile += "# communication options" + newline;
+ makefile += "COMMON_FLAGS += -DMPARM_SCRATCHPAD_QUEUE"
+ + newline;
+ makefile+="COMMON_FLAGS += -DQUEUE_BUFF_IN_PRODUCER "
+ + "-Dshaper_PROCESSOR" + newline;
+ makefile+="#COMMON_FLAGS += -DQUEUE_BUFF_IN_PRODUCER_DMA "
+ + "-Dshaper_PROCESSOR" + newline;
+ makefile+="#COMMON_FLAGS += -DQUEUE_BUFF_IN_CONSUMER "
+ + "-Dshaper_PROCESSOR" + newline;
+ makefile+="#COMMON_FLAGS += -DQUEUE_BUFF_IN_CONSUMER_DMA "
+ + "-Dshaper_PROCESSOR" + newline;
+ makefile+="#COMMON_FLAGS += -DQUEUE_BUFF_IN_SHARDMEM "
+ + "-Dshaper_PROCESSOR" + newline;
+
+ int shaperProcessorID;
+ if (_ui.getMappingFileName() == null) {
+ shaperProcessorID = pn.getProcessList().size();
+ } else {
+ ArchiXmlParser archParser = new ArchiXmlParser();
+ Architecture arch = archParser.
+ doParse(_ui.getPlatformFileName());
+ MapXmlParser mappingParser = new MapXmlParser(pn, arch);
+ Mapping mapping = mappingParser.
+ doParse(_ui.getMappingFileName());
+ shaperProcessorID = mapping.getProcessorList().size();
+ }
+ makefile +="#COMMON_FLAGS += -DQUEUE_BUFF_SHAPER "
+ + "-Dshaper_PROCESSOR=" + shaperProcessorID + newline;
+
+ makefile += newline;
+ makefile += "LIBFILECXX = "
+ + "$(SS_SEMAPHORE_LIB_PATH)/ss_semaphore.cpp "
+ + "$(SCRATCH_QUEUE_LIB_PATH)/scratch_queue.cpp"
+ + newline;
+ makefile += "VPATH = SCRATCH_QUEUE_LIB_PATH" + newline;
+ }
+
+ makefile += "" + newline;
+ makefile += "# C source names" + newline;
+ if (_ui.getRtemsBSP().equals("pc386")) {
+ makefile += "CSRCS = main.c rtems_process_wrapper.c ";
+ for (String basename : pn.getProcessBasenames()) {
+ makefile += basename + "_wrapper.c ";
+ }
+ }
+ makefile += newline;
+ makefile += "COBJS_ = $(CSRCS:.c=.o)" + newline;
+ makefile += "COBJS = $(COBJS_:%=%)" + newline;
+ makefile += "" + newline;
+ makefile += "# C++ source names" + newline;
+ makefile += "CXXSRCS = appsupport.c" + newline;
+
+ if (_ui.getRtemsBSP().equals("mparm")) {
+ makefile += "CXXSRCS += main.c traffic_shaping.c "
+ + "rtems_process_wrapper.c ";
+ Vector<String> pList = new Vector<String>();
+ for (Process p : pn.getProcessList()) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ makefile += p.getBasename() + "_wrapper.c ";
+ pList.add(basename);
+ }
+ }
+ makefile += newline;
+ makefile += "CXXSRCS += $(LIBFILECXX)" + newline;
+ }
+
+ makefile += newline;
+ makefile += newline;
+ makefile += "CXXOBJS_ = $(CXXSRCS:.cpp=.o)" + newline;
+ makefile += "CXXOBJS = $(CXXOBJS_:%=%)" + newline;
+ makefile += "" + newline;
+ makefile += "# AS source names" + newline;
+ makefile += "ASSRCS =" + newline;
+ makefile += "ASOBJS_ = $(ASSRCS:.s=.o)" + newline;
+ makefile += "ASOBJS = $(ASOBJS_:%=%)" + newline;
+ makefile += "" + newline;
+ makefile += "# Libraries" + newline;
+ makefile += "LIBS = -lrtemsall -lc" + newline;
+ makefile += "" + newline;
+ makefile += "include $(RTEMS_MAKEFILE_PATH)/Makefile.inc"
+ + newline;
+ makefile += "include $(RTEMS_CUSTOM)" + newline;
+ makefile += "include $(PROJECT_ROOT)/make/leaf.cfg" + newline;
+ makefile += "" + newline;
+ makefile += "#CXXFLAGS += -DAUTOSTARTMEASURING" + newline;
+ makefile += "#CXXFLAGS += -DVERBOSE" + newline;
+ makefile += "CXXFLAGS += -I$(SWARMDIR)/core" + newline;
+ makefile += "CFLAGS += -I$(SWARMDIR)/core" + newline;
+
+ if (_ui.getRtemsBSP().equals("mparm")) {
+ makefile += "CXXFLAGS += $(COMMON_FLAGS) -I${PWD}" + newline;
+ makefile += "CFLAGS += $(COMMON_FLAGS) -I${PWD}" + newline;
+
+ makefile += newline;
+ makefile += "#### for calibration" + newline;
+ makefile += "CXXFLAGS += -Ilib" + newline;
+ makefile += "CXXFLAGS += -D_GLIBCPP_HAVE_WCHAR_H "
+ + "-D_GLIBCPP_HAVE_MBSTATE_T" + newline;
+ makefile += "CXXFLAGS += -DWORKLOAD_EXTRACT" + newline;
+ makefile += "CXXFLAGS += -DPRINTF_TO_DEBUG" + newline;
+ }
+ makefile += "" + newline;
+ makefile += "SRCS=$(H_FILES)" + newline;
+ makefile += "OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS)" + newline;
+ makefile += "" + newline;
+ makefile += "all: ${ARCH} $(SRCS) $(PGM) " + newline;
+ makefile += "" + newline;
+ makefile += "$(PGM): $(OBJS) " + newline;
+ makefile += "\t$(make-exe)" + newline;
+ makefile += "clean:" + newline;
+ makefile += "\t-rm -f ${SS_SEMAPHORE_LIB_PATH}/*.o " +
+ "${SCRATCH_QUEUE_LIB_PATH}/*.o" + newline;
+
+ return makefile;
+ }
+
+ /**
+ * Create a makefile for the pc386 board support package.
+ *
+ * @param pn process network
+ * @return makefile for pc386 board support package
+ */
+ protected String getPc386Makefile(ProcessNetwork pn) {
+ String makefile = "";
+ String newline = System.getProperty("line.separator");
+ makefile += "EXEC=main.exe" + newline;
+ makefile += "PGM=${ARCH}/$(EXEC)" + newline;
+ makefile += newline;
+ makefile += "# optional managers required" + newline;
+ makefile += "MANAGERS=all" + newline;
+ makefile += newline;
+ makefile += "# C source names" + newline;
+ makefile += "CSRCS = main.c rtems_process_wrapper.c ";
+ for (String basename : pn.getProcessBasenames()) {
+ makefile += basename + "_wrapper.c ";
+ }
+ for (Configuration conf : pn.getCfgList()) {
+ if (conf.getName().equals("EXTERNAL_SRC")) {
+ makefile += conf.getValue();
+ }
+ }
+ makefile += newline;
+ makefile += "COBJS_ = $(CSRCS:.c=.o)" + newline;
+ makefile += "COBJS = $(COBJS_:%=${ARCH}/%)" + newline;
+ makefile += newline;
+ makefile += "# C++ source names" + newline;
+ makefile += "CXXSRCS =" + newline;
+ makefile += "CXXOBJS_ = $(CXXSRCS:.cc=.o)" + newline;
+ makefile += "CXXOBJS = $(CXXOBJS_:%=${ARCH}/%)" + newline;
+ makefile += newline;
+ makefile += "# AS source names" + newline;
+ makefile += "ASSRCS =" + newline;
+ makefile += "ASOBJS_ = $(ASSRCS:.s=.o)" + newline;
+ makefile += "ASOBJS = $(ASOBJS_:%=${ARCH}/%)" + newline;
+ makefile += newline;
+ makefile += "# Libraries" + newline;
+ makefile += "LIBS = -lrtemsall -lc ";
+ for (Configuration conf : pn.getCfgList()) {
+ if (conf.getName().equals("DYNAMIC_LINK"))
+ makefile += conf.getValue() + newline;
+ }
+ makefile += newline;
+ makefile += "include $(RTEMS_MAKEFILE_PATH)/Makefile.inc"
+ + newline;
+ makefile += newline;
+ makefile += "include $(RTEMS_CUSTOM)" + newline;
+ makefile += "include $(PROJECT_ROOT)/make/leaf.cfg" + newline;
+ makefile += newline;
+ makefile += "OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS)" + newline;
+ makefile += newline;
+ makefile += "all: ${ARCH} $(PGM)" + newline;
+ makefile += newline;
+ makefile += "$(PGM): $(OBJS)" + newline;
+ makefile += "\t$(make-exe)" + newline;
+ return makefile;
+ }
+
+ protected String _dir = null;
+}
--- /dev/null
+/* $Id: RtemsModuleVisitor.java 114 2010-07-05 07:47:02Z haidw $ */
+package dol.visitor.rtems;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Vector;
+
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.mapping.ComputationBinding;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.mapping.Schedule;
+import dol.datamodel.mapping.ScheduleEntry;
+import dol.datamodel.mapping.SchedulingPolicy;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.main.UserInterface;
+import dol.parser.xml.archischema.ArchiXmlParser;
+import dol.parser.xml.mapschema.MapXmlParser;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * the main program.
+ */
+public class RtemsModuleVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of this file
+ */
+ public RtemsModuleVisitor(String dir, HashMap<Port, Integer> portMap) {
+ _dir = dir;
+ _portMap = portMap;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ _ui = UserInterface.getInstance();
+ String filename = _dir + _delimiter + "main.c";
+ OutputStream file = new FileOutputStream(filename);
+ _mainPS = new CodePrintStream(file);
+
+ Vector<Process> pList = x.getProcessList();
+ Vector<String> processList = new Vector<String>();
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!processList.contains(basename)) {
+ processList.add(basename);
+ }
+ }
+
+ Architecture arch = null;
+ Mapping mapping = null;
+
+ //create header section
+ if (_ui.getRtemsBSP().equals("pc386")) {
+ _mainPS.println("#include <bsp.h>");
+ _mainPS.println("#include <stdlib.h>");
+ _mainPS.println("#include <stdio.h>");
+ _mainPS.println("#include <inttypes.h>");
+ _mainPS.println();
+ _mainPS.println("rtems_task Init(rtems_task_argument argument);");
+ _mainPS.println();
+ _mainPS.println("#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER");
+ _mainPS.println("#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER");
+ _mainPS.println("#define CONFIGURE_RTEMS_INIT_TASKS_TABLE");
+ _mainPS.println("#define CONFIGURE_MAXIMUM_TASKS "
+ + (x.getProcessList().size() + 2));
+ _mainPS.println("#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES "
+ + x.getChannelList().size());
+ _mainPS.println("#define CONFIGURE_INIT");
+ _mainPS.println("#include <rtems/confdefs.h>");
+ _mainPS.println();
+ } else if (_ui.getRtemsBSP().equals("mparm")) {
+ _mainPS.println("#define TEST_INIT");
+ _mainPS.println("#include <bsp.h>");
+ _mainPS.println("#include <stdlib.h>");
+ _mainPS.println("#include <stdio.h>");
+ _mainPS.println();
+ _mainPS.println("#define RTEMS_TRACE_MAIN_APP");
+ _mainPS.println("#include \"system.h\"");
+ _mainPS.println("#include \"appsupport.h\"");
+ _mainPS.println("#include \"scratch_queue.h\"");
+ _mainPS.println();
+ }
+
+ _mainPS.println("#include \"dol.h\"");
+ _mainPS.println("#include \"rtems_process_wrapper.h\"");
+ _mainPS.println();
+
+ if (_ui.getRtemsBSP().equals("pc386")) {
+ _mainPS.println("rtems_task CleanupTask(rtems_task_argument arg);");
+ _mainPS.println("rtems_id queue_id["
+ + x.getChannelList().size() + "];");
+ _mainPS.println();
+ } else if (_ui.getRtemsBSP().equals("mparm")) {
+ //if no mapping is provided, map each process to a new
+ //processor
+ //shaper
+ _mainPS.println("#ifdef QUEUE_BUFF_SHAPER");
+ _mainPS.println("#include \"traffic_shaping.h\"");
+ //_mainPS.println("#define shaper_PROCESSOR "
+ // + (pList.size()+1));
+ _mainPS.println("#endif // shaper");
+ _mainPS.println();
+
+ if (_ui.getMappingFileName() == null) {
+
+ int i = 0;
+ for (Process p : pList) {
+ _mainPS.println("#define " + p.getName()
+ + "_PROCESSOR " + ++i); //count from 1
+ }
+ _mainPS.println();
+
+ _mainPS.print("unsigned int number_of_processes["
+ + pList.size() + "] = { ");
+ for (i = 0; i < pList.size(); i++) {
+ _mainPS.print("1, ");
+ }
+ _mainPS.println("};");
+ _mainPS.println();
+
+ } else { //map processes according to mapping file
+ ArchiXmlParser archParser = new ArchiXmlParser();
+ arch = archParser.doParse(_ui.getPlatformFileName());
+ MapXmlParser mappingParser = new MapXmlParser(x, arch);
+ mapping = mappingParser.doParse(_ui.getMappingFileName());
+ int numOfUsedProcessors = mapping.getProcessorList().size();
+ int numOfProcessors = arch.getProcessorList().size();
+ int processesPerProcessor[] = new int[numOfProcessors];
+
+ // need to check processors used start from 0 and
+ //continuous
+ for (Process p : pList) {
+ for (ComputationBinding b : mapping.getCompBindList()){
+ int processorIndex = Integer.valueOf(
+ b.getProcessor().getName().
+ replaceAll(".*_", ""));
+ if (b.getProcess().getName().
+ equals(p.getName())) {
+ processesPerProcessor[processorIndex]++;
+ //processor indices start at 1 in MPARM
+ _mainPS.println("#define " + p.getName()
+ + "_PROCESSOR "
+ + (processorIndex + 1));
+ }
+ }
+ }
+
+
+ for (int i=0; i < numOfUsedProcessors; i++) {
+ if (processesPerProcessor[i] < 1)
+ throw new Exception("No process is mapped to "
+ + "PROCESSOR[" + i + "]. For the MPARM "
+ + "platform, processors should be used "
+ + "starting from 0 until N (in the "
+ + "generated code, from 1 to N + 1), and "
+ + "every processor between 0 and N "
+ + "should have at least one process "
+ + "mapped on it!");
+ }
+
+ _mainPS.println();
+ /*
+ _mainPS.println("#ifdef QUEUE_BUFF_SHAPER");
+ _mainPS.println("#define shaper_PROCESSOR "
+ + (numOfUsedProcessors+1));
+ _mainPS.println("#endif // shaper");
+ _mainPS.println();
+ */
+ _mainPS.print("unsigned int number_of_processes[]"
+ + " = { ");
+ for (int i = 0; i < numOfUsedProcessors; i++) {
+ _mainPS.print(processesPerProcessor[i] + ", ");
+ }
+ _mainPS.println("};");
+ _mainPS.println();
+ }
+
+ _mainPS.println("unsigned int active_processes;");
+ _mainPS.println("inline void processor_init() "
+ + "{active_processes"
+ + " = number_of_processes[get_id() - 1];}");
+ _mainPS.println();
+
+ for (Process p : pList) {
+ _mainPS.println("void " + "rtems_" + p.getName()
+ + "_init(rtems_task_argument arg);");
+ }
+ _mainPS.println();
+ }
+
+ for (String pName : x.getProcessBasenames()) {
+ _mainPS.println("extern rtems_task " + pName
+ + "_task(rtems_task_argument argument);");
+ }
+ _mainPS.println();
+
+ //declare processes and channels
+ for (Process process : x.getProcessList()) {
+ _mainPS.println("RtemsProcessWrapper *" + process.getName()
+ + "_wrapper;");
+ }
+ _mainPS.println();
+
+ _mainPS.println("#ifdef PRINTF_TO_DEBUG");
+ _mainPS.println("#undef printf");
+ _mainPS.println("#define printf(...) \\");
+ _mainPS.println(" do { \\");
+ _mainPS.println(" char _buffer[128]; \\");
+ _mainPS.println(" sprintf(_buffer, __VA_ARGS__); \\");
+ _mainPS.println(" SHOW_DEBUG((int)_buffer); \\");
+ _mainPS.println(" } while (0)");
+ _mainPS.println("#endif");
+ _mainPS.println();
+ _mainPS.println("#ifdef WORKLOAD_EXTRACT");
+ _mainPS.println("void callback(int code, int* arg, int size) "
+ + "{");
+ _mainPS.println(" long unsigned int time = get_cycle1();");
+ _mainPS.println(" Thread_Control *x = "
+ + "(Thread_Control*)arg;");
+ _mainPS.println(" SHOW_DEBUG(\"log callback\");");
+ _mainPS.println(" SHOW_DEBUG_INT((int)time);");
+ _mainPS.println(" SHOW_DEBUG_INT(x->Object.id);");
+ _mainPS.println("}");
+ _mainPS.println("#endif");
+ _mainPS.println();
+ _mainPS.println("rtems_id timer_sem_id;");
+ _mainPS.println();
+ //RTEMS init task
+ _mainPS.println("/**");
+ _mainPS.println(" *");
+ _mainPS.println(" */");
+ _mainPS.println("rtems_task Init(rtems_task_argument arg) {");
+
+ if (_ui.getRtemsBSP().equals("mparm")) {
+ // //////////////////// mparm /////////////////////////
+ int processCount = 0;
+
+ _mainPS.println(" rtems_id task_id;");
+ _mainPS.println(" rtems_status_code status;");
+ _mainPS.println();
+ _mainPS.println(" status = rtems_semaphore_create(rtems_build_name('c','s','e','m'), 1, RTEMS_BINARY_SEMAPHORE |RTEMS_NO_PRIORITY_CEILING |RTEMS_LOCAL |RTEMS_PRIORITY, 0,&timer_sem_id);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] Could not create semaphore (status %d).\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+
+
+ _mainPS.println();
+
+ _mainPS.println(" scratch_queue_autoinit_system();");
+ _mainPS.println();
+
+ _mainPS.println("#ifdef WORKLOAD_EXTRACT");
+ _mainPS.println(" rtems_monitor_register_callback"
+ + "(callback);");
+ for (Channel c : x.getChannelList()) {
+ _mainPS.println(" SHOW_DEBUG(\"log "
+ + "create_channel\");");
+ _mainPS.println(" SHOW_DEBUG(\"log " + c.getName()
+ + "\");");
+ _mainPS.println(" SHOW_DEBUG_INT((int)"
+ + (c.getSize() * c.getTokenSize()) + ");");
+ }
+ _mainPS.println("#endif");
+
+ //shaper process
+ _mainPS.println("#ifdef QUEUE_BUFF_SHAPER");
+ _mainPS.println(" if ((get_id()-1) == shaper_PROCESSOR) "
+ + "{");
+ _mainPS.println(" rtems_name name = rtems_build_name"
+ +"('s', 's', '0', ' ');");
+ _mainPS.println();
+
+ // create pre task
+ _mainPS.println(" //one more init to prevent the"
+ + "blocking instatiation of scrach queue");
+ _mainPS.println(" status = rtems_task_create(");
+ _mainPS.println(" name,");
+ _mainPS.println(" 1,");
+ _mainPS.println(" RTEMS_MINIMUM_STACK_SIZE,");
+ _mainPS.println(" RTEMS_DEFAULT_MODES,");
+ _mainPS.println(" RTEMS_LOCAL,");
+ _mainPS.println(" &task_id, -1);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not create init shaper"
+ + "(status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println();
+
+ // start pre init
+ _mainPS.println(" status = rtems_task_start(task_id, "
+ + "shaping_init, arg);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not start init shaping"
+ + " (status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println(" }");
+ _mainPS.println("#endif // QUEUE_BUFF_SHAPER");
+ _mainPS.println();
+
+ for (Process process : x.getProcessList()) {
+ _mainPS.println(" if (get_id() == "
+ + process.getName() + "_PROCESSOR) {");
+ _mainPS.println(" processor_init();");
+ _mainPS.println(" rtems_name name = "
+ + "rtems_build_name"
+ + "('p', 'i', 0x" + ++processCount
+ + ", ' ');");
+ _mainPS.println();
+
+ // create pre task
+ _mainPS.println(" //one more init to prevent the"
+ + "blocking instatiation of scrach queue");
+ _mainPS.println(" status = rtems_task_create(");
+ _mainPS.println(" name,");
+ _mainPS.println(" 1,");
+ _mainPS.println(" RTEMS_MINIMUM_STACK_SIZE"
+ + ",");
+ _mainPS.println(" RTEMS_DEFAULT_MODES,");
+ _mainPS.println(" RTEMS_LOCAL,");
+ _mainPS.println(" &task_id, -1);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) "
+ + "{");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not create init task["
+ + process.getName() + "] "
+ +"(status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println();
+
+ // start pre init
+ _mainPS.println(" status = rtems_task_start(task_id, "
+ + "rtems_" + process.getName()
+ + "_init, arg);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not start init task [ "
+ + process.getName()
+ + "] (status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ /*
+ _mainPS.println(" rtems_" + process.getName()
+ + "_init(arg);");
+ _mainPS.println(" rtems_task_delete(RTEMS_SELF);");
+ */
+ _mainPS.println(" }");
+ _mainPS.println();
+ }
+
+ // shaper process
+ _mainPS.println("#ifdef QUEUE_BUFF_SHAPER");
+ _mainPS.println(" if ((get_id()-1) == shaper_PROCESSOR) "
+ + "{");
+ _mainPS.println(" rtems_name name = rtems_build_name"
+ +"('s', 's', '0', ' ');");
+ _mainPS.println();
+
+ // create pre task
+ _mainPS.println(" //one more init to prevent the"
+ + "blocking instatiation of scrach queue");
+ _mainPS.println(" status = rtems_task_create(");
+ _mainPS.println(" name,");
+ _mainPS.println(" 128,");
+ _mainPS.println(" RTEMS_MINIMUM_STACK_SIZE,");
+ _mainPS.println(" RTEMS_DEFAULT_MODES,");
+ _mainPS.println(" RTEMS_LOCAL,");
+ _mainPS.println(" &task_id, -1);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not create init shaper"
+ +"(status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println();
+
+ // start pre init
+ _mainPS.println(" status = rtems_task_start(task_id, "
+ + "shaping_init, arg);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not start init shaping"
+ + " (status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println(" }");
+ _mainPS.println("#endif // QUEUE_BUFF_SHAPER");
+ _mainPS.println();
+
+ _mainPS.println("if (number_of_processes[get_id() - 1]"
+ + " == 0) {");
+ _mainPS.println(" printf(\"No process on processor "
+ + "%d.\", get_id());");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println("}");
+ _mainPS.println();
+
+ _mainPS.println(" rtems_task_delete(RTEMS_SELF);");
+ _mainPS.println("}");
+ _mainPS.println();
+ // end of init
+
+ processCount = 0;
+ for (Process process : x.getProcessList()) {
+ String processName = process.getName();
+ _mainPS.println("void rtems_" + process.getName()
+ + "_init(rtems_task_argument arg) {");
+ _mainPS.println(" rtems_id task_id;");
+ _mainPS.println(" rtems_status_code status;");
+
+
+ _mainPS.println(" " + process.getName()
+ + "_wrapper = "
+ + "(RtemsProcessWrapper *)malloc"
+ + "(sizeof(RtemsProcessWrapper));");
+
+ int numOfOutports = process.getNumOfOutports();
+ int numOfInports = process.getNumOfInports();
+ if (numOfOutports > 0) {
+ _mainPS.println(" int* "
+ + process.getName()
+ + "_out_port_id = (int *)malloc("
+ + numOfOutports
+ + " * sizeof(int));");
+ _mainPS.println(" SCRATCH_QUEUE_PRODUCER **"
+ + process.getName()
+ + "_out_queue_id = "
+ + "(SCRATCH_QUEUE_PRODUCER **)"
+ + "malloc("
+ + numOfOutports
+ + "*sizeof(SCRATCH_QUEUE_PRODUCER));");
+ }
+
+ if (numOfInports > 0) {
+ _mainPS.println(" int *"
+ + process.getName()
+ + "_in_port_id = (int *)malloc("
+ + numOfInports
+ + " * sizeof(int));");
+ _mainPS.println(" SCRATCH_QUEUE_CONSUMER **"
+ + process.getName()
+ + "_in_queue_id = "
+ + "(SCRATCH_QUEUE_CONSUMER **)"
+ + "malloc("
+ + numOfOutports
+ + "*sizeof(SCRATCH_QUEUE_CONSUMER));");
+ }
+ _mainPS.println();
+
+ // create task
+ _mainPS.println(" status = rtems_task_create(");
+ _mainPS.println(" " + ++processCount + ",");
+ _mainPS.println(" 1,");
+ _mainPS.println(" RTEMS_MINIMUM_STACK_SIZE,");
+ _mainPS.println(" RTEMS_DEFAULT_MODES,");
+ _mainPS.println(" RTEMS_LOCAL,");
+ _mainPS.println(" &task_id, -1);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not create task["
+ + processName + "] "
+ +"(status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+
+ _mainPS.println("#ifdef WORKLOAD_EXTRACT");
+ _mainPS.println(" SHOW_DEBUG(\"log create_task\");");
+ _mainPS.println(" SHOW_DEBUG_INT(task_id);");
+ _mainPS.println(" SHOW_DEBUG(\"log " + processName + "\");");
+ for (Port port : process.getPortList()) {
+ Channel c = (Channel) port.getPeerResource();
+ if (port.isInPort()) {
+ _mainPS.println(" SHOW_DEBUG(\"log in_port\");");
+ _mainPS.println(" SHOW_DEBUG_INT((int)" + _portMap.get(port) + ");");
+ _mainPS.println(" SHOW_DEBUG(\"log " + c.getName() + "\");");
+ }
+ if (port.isOutPort()) {
+ _mainPS.println(" SHOW_DEBUG(\"log out_port\");");
+ _mainPS.println(" SHOW_DEBUG_INT((int)" + _portMap.get(port) + ");");
+ _mainPS.println(" SHOW_DEBUG(\"log " + c.getName() + "\");");
+ }
+ }
+ _mainPS.println("#endif");
+ _mainPS.println();
+
+ // connect ports to channels
+ HashMap<Channel, Integer> channel_map =
+ new HashMap<Channel, Integer>();
+ int channelCount = 1;
+ for (Channel c : x.getChannelList()) {
+ channel_map.put(c, channelCount++);
+ }
+ _mainPS.println();
+
+ // fill the wrapper, instantiate queues
+ int i = 0, j = 0;
+ for (Port port : process.getPortList()) {
+ Channel c = (Channel)(port.getPeerResource());
+ if (port.isInPort()) {
+ _mainPS.println(" " + processName + "_in_port_id["
+ + i + "] = "
+ + _portMap.get(port) + ";");
+ _mainPS.println(" " + processName
+ + "_in_queue_id["
+ + i + "] = ");
+ _mainPS.println("#if defined (QUEUE_BUFF_IN_PRODUCER) || (QUEUE_BUFF_IN_PRODUCER_DMA)");
+ _mainPS.println(" scratch_queue_autoinit_consumer("
+ + channel_map.get(c)
+ + ", true);");
+ _mainPS.println("#elif defined (QUEUE_BUFF_IN_CONSUMER) || (QUEUE_BUFF_IN_CONSUMER_DMA)");
+ _mainPS.println(" scratch_queue_autoinit_consumer("
+ + c.getOrigin().getName()
+ + "_PROCESSOR, "
+ + channel_map.get(c) + ", "
+ + c.getSize() + ", "
+ + c.getTokenSize()
+ + ");");
+ _mainPS.println("#elif defined (QUEUE_BUFF_IN_SHARDMEM)");
+ _mainPS.println(" scratch_queue_autoinit_consumer("
+ + channel_map.get(c)
+ + ", true);");
+ _mainPS.println("#elif defined (QUEUE_BUFF_SHAPER)");
+ _mainPS.println(" scratch_queue_autoinit_consumer("
+ + channel_map.get(c)
+ + ");");
+ _mainPS.println("#endif");
+
+
+ i++;
+ } else if (port.isOutPort()) {
+ _mainPS.println(" " + processName+"_out_port_id["
+ + j + "] = "
+ + _portMap.get(port) + ";");
+ _mainPS.println(" " + processName
+ + "_out_queue_id["
+ + j + "] = ");
+
+ _mainPS.println("#if defined (QUEUE_BUFF_IN_PRODUCER) || (QUEUE_BUFF_IN_PRODUCER_DMA)");
+ _mainPS.println(" scratch_queue_autoinit_producer("
+ + c.getTarget().getName()
+ + "_PROCESSOR,"
+ + channel_map.get(c) + ", "
+ + c.getSize() + ", "
+ + c.getTokenSize()
+ + ", 0);");
+ _mainPS.println("#elif defined (QUEUE_BUFF_IN_CONSUMER) || (QUEUE_BUFF_IN_CONSUMER_DMA)");
+ _mainPS.println(" scratch_queue_autoinit_producer("
+ + channel_map.get(c)
+ + ", true);");
+ _mainPS.println("#elif defined (QUEUE_BUFF_IN_SHARDMEM)");
+ _mainPS.println(" scratch_queue_autoinit_producer("
+ + c.getTarget().getName()
+ + "_PROCESSOR,"
+ + channel_map.get(c) + ", "
+ + c.getSize() + ", "
+ + c.getTokenSize()
+ + ", 1);");
+ _mainPS.println("#elif defined (QUEUE_BUFF_SHAPER)");
+ _mainPS.println(" scratch_queue_autoinit_producer("
+ + c.getTarget().getName()
+ + "_PROCESSOR,"
+ + channel_map.get(c) + ", "
+ + c.getSize() + ", "
+ + c.getTokenSize()
+ + ");");
+ _mainPS.println("#endif");
+
+ j++;
+ }
+ }
+
+ if (numOfInports > 0) {
+ _mainPS.println(" " + processName
+ + "_wrapper->in_port_id = "
+ + processName
+ + "_in_port_id;");
+ _mainPS.println(" " + processName
+ + "_wrapper->in_queue_id = "
+ + processName
+ + "_in_queue_id;");
+ _mainPS.println(" " + processName
+ + "_wrapper->number_of_in_ports = "
+ + numOfInports + ";");
+ }
+
+ if (numOfOutports > 0) {
+ _mainPS.println(" " + processName
+ + "_wrapper->out_port_id = "
+ + processName
+ + "_out_port_id;");
+ _mainPS.println(" " + processName
+ + "_wrapper->out_queue_id = "
+ + processName
+ + "_out_queue_id;");
+ _mainPS.println(" " + processName
+ + "_wrapper->number_of_out_ports = "
+ + numOfOutports + ";");
+ }
+
+ _mainPS.println(" " + processName
+ + "_wrapper->is_detached = 0;");
+
+ int priority = 127;
+ if (mapping != null) {
+ Schedule s = mapping.getScheduleByResource(
+ process.getProcessor().getName());
+ if (s != null && s.getSchedPolicy() ==
+ SchedulingPolicy.FIXEDPRIORITY) {
+ ScheduleEntry e = s.getScheduleEntry(
+ process.getName());
+ if (e != null) {
+ String value = e.getCfgValue("priority");
+ if (value != null) {
+ priority = Integer.parseInt(value);
+ }
+ }
+ }
+ }
+ _mainPS.println(" " + processName
+ + "_wrapper->priority = " + priority + ";");
+
+ _mainPS.println(" " + processName
+ + "_wrapper->name = (char *)malloc(("
+ + processName.length()
+ + " + 1) * sizeof(char));");
+ _mainPS.println(" strcpy(" + processName
+ + "_wrapper->name, " + "\""
+ + processName + "\");");
+ _mainPS.println();
+
+ _mainPS.println(" status = rtems_task_start("
+ + "task_id, " + process.getBasename()
+ + "_task, " + "(rtems_task_argument)"
+ + process.getName() + "_wrapper);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) "
+ + "{");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not start " + process.getName()
+ + " (status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println(" rtems_task_delete(RTEMS_SELF);");
+ _mainPS.println("}");
+ _mainPS.println();
+ _mainPS.println();
+ }
+ } else if (_ui.getRtemsBSP().equals("pc386")) {
+ // //////////////////// pc386 ////////////////////////
+ _mainPS.println(" int j;");
+ _mainPS.println(" rtems_id task_id[" +
+ + (x.getProcessList().size() + 1) + "];");
+ _mainPS.println(" rtems_status_code status;");
+ _mainPS.println();
+
+ //initialize process-specific information
+ for (Process process : x.getProcessList()) {
+ int numberOfPorts = x.getProcess(process.getName())
+ .getPortList().size();
+ _mainPS.println(" " + process.getName()
+ + "_wrapper = "
+ + "malloc(sizeof(RtemsProcessWrapper));");
+ _mainPS.println(" int *"
+ + process.getName() + "_port_id = malloc("
+ + numberOfPorts + " * sizeof(int));");
+ _mainPS.println(" int *"
+ + process.getName()
+ + "_port_queue_id = malloc("
+ + numberOfPorts + " * sizeof(int));");
+ _mainPS.println();
+ }
+
+ //create a task for each process
+ _mainPS.println(" for (j = 0; j < "
+ + (x.getProcessList().size()+1) + "; j++) {");
+ _mainPS.println(" status = rtems_task_create(");
+ _mainPS.println(" j + 1,");
+ _mainPS.println(" 128,");
+ _mainPS.println(" RTEMS_MINIMUM_STACK_SIZE,");
+ _mainPS.println(" RTEMS_DEFAULT_MODES,");
+ _mainPS.println(" RTEMS_DEFAULT_ATTRIBUTES,");
+ _mainPS.println(" &(task_id[j]));");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not create task[%d] (status %d).\\n\", "
+ + "(int)j, status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println(" }");
+ _mainPS.println();
+
+ //create a message queue for each channel
+ int j = 0;
+ for (Channel channel : x.getChannelList()) {
+ _mainPS.println(" status = "
+ + "rtems_message_queue_create(");
+ _mainPS.println(" " + (j + 1) + ",");
+ _mainPS.println(" " + channel.getSize()
+ + ",");
+ _mainPS.println(" 1,");
+ _mainPS.println(" RTEMS_DEFAULT_ATTR"
+ + "IBUTES,");
+ _mainPS.println(" &queue_id[" + j + "]);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) "
+ + "{");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not create queue[" + j
+ + "] (status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println();
+ j++;
+ }
+
+ //connect ports to channels
+ HashMap<Channel, Integer> channel_map =
+ new HashMap<Channel, Integer>();
+ j = 0;
+ for (Channel c : x.getChannelList()) {
+ channel_map.put(c, j++);
+ }
+
+ for (Process process : x.getProcessList()) {
+ String processName = process.getName();
+ int i = 0;
+ for (Port port : process.getPortList()) {
+ Channel c = (Channel)(port.getPeerResource());
+
+ _mainPS.println(" " + processName + "_port_id["
+ + i + "] = "
+ + _portMap.get(port) + ";");
+ _mainPS.println(" " + processName
+ + "_port_queue_id[" + i + "] = queue_id["
+ + channel_map.get(c) + "];");
+ i++;
+ }
+ _mainPS.println(" " + processName
+ + "_wrapper->port_id = " + processName
+ + "_port_id;");
+ _mainPS.println(" " + processName
+ + "_wrapper->port_queue_id = "
+ + processName
+ + "_port_queue_id;");
+ _mainPS.println(" " + processName
+ + "_wrapper->number_of_ports = "
+ + i + ";");
+ _mainPS.println(" " + processName
+ + "_wrapper->is_detached = 0;");
+ _mainPS.println(" " + processName
+ + "_wrapper->name = malloc(("
+ + processName.length()
+ + " + 1) * sizeof(char));");
+ _mainPS.println(" strcpy(" + processName
+ + "_wrapper->name, " + "\""
+ + processName + "\");");
+ _mainPS.println();
+ }
+
+ //start cleanup task
+ _mainPS.println(" printf(\"[init ] "
+ + "Start cleanup.\\n\");");
+ _mainPS.println(" status = rtems_task_start(task_id[0], "
+ + "CleanupTask, 0);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) {");
+ _mainPS.println(" printf(\"[init ] Could not start "
+ + "cleanup (status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println();
+
+ //start processes
+ j = 1;
+ for (Process process : x.getProcessList()) {
+ _mainPS.println(" printf(\"[init ] Start "
+ + process.getName() + ".\\n\");");
+ _mainPS.println(" status = rtems_task_start(task_id["
+ + j + "], " + process.getBasename()
+ + "_task, "
+ + "(rtems_task_argument)"
+ + process.getName()
+ + "_wrapper);");
+ _mainPS.println(" if (status != RTEMS_SUCCESSFUL) "
+ + "{");
+ _mainPS.println(" printf(\"[init ] "
+ + "Could not start " + process.getName()
+ + " (status %d).\\n\", status);");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println(" }");
+ _mainPS.println();
+ j++;
+ }
+
+ _mainPS.println(" printf(\"[init ] Done.\\n\");");
+ _mainPS.println(" rtems_task_delete(RTEMS_SELF);");
+ _mainPS.println("}");
+ _mainPS.println();
+
+ _mainPS.println("rtems_task CleanupTask(rtems_task_argument "
+ + "argument) {");
+ _mainPS.println(" printf(\"[cleanup ] Started.\\n\");");
+ _mainPS.println(" do {");
+ _mainPS.println(" rtems_task_wake_after(0);");
+ _mainPS.println(" } while (");
+ j = 0;
+ for (Process process : x.getProcessList()) {
+ _mainPS.print(" !("
+ + process.getName()
+ + "_wrapper->is_detached)");
+ j++;
+ if (j < x.getProcessList().size()) {
+ _mainPS.println(" || ");
+ } else {
+ _mainPS.println(");");
+ }
+ }
+ _mainPS.println();
+ _mainPS.println(" printf(\"[cleanup ] Shutdown.\\n\");");
+ _mainPS.println(" rtems_shutdown_executive(0);");
+ _mainPS.println("}");
+ _mainPS.println();
+ }
+ }
+ catch (Exception e) {
+ System.out.println("RtemsModuleVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param x process that needs to be processed
+ */
+ public void visitComponent(Process x) {
+ }
+
+ /**
+ *
+ * @param x channel that needs to be processed
+ */
+ public void visitComponent(Channel x) {
+ }
+
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+ protected HashMap<Port, Integer> _portMap;
+}
--- /dev/null
+/* $Id: RtemsProcessVisitor.java 213 2010-10-20 09:40:59Z khuang $ */
+package dol.visitor.rtems;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Vector;
+
+import dol.datamodel.pn.Configuration;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.SourceCode;
+import dol.util.Copier;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a wrapper class for a process.
+ */
+public class RtemsProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir target directory
+ */
+ public RtemsProcessVisitor(String dir,
+ HashMap<Port, Integer> portMap,
+ HashMap<Process, Integer> sinkMap) {
+ _dir = dir;
+ _portMap = portMap;
+ _sinkMap = sinkMap;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be processed
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ Vector<String> pList = new Vector<String>();
+
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ pList.add(basename);
+ p.accept(this);
+ }
+ }
+ }
+ catch (Exception e) {
+ System.out.println("RtemsProcessVisitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Visit process.
+ *
+ * @param p process that needs to be processed
+ */
+ public void visitComponent(Process p) {
+ try {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.c";
+ File process_file = new File(filename);
+ File pattern_file = new File(_dir + _delimiter
+ + "process_wrapper_template.c");
+ new Copier().copyFile(pattern_file, process_file);
+
+ String includes = "";
+ for (SourceCode code : p.getSrcList()) {
+ includes += "#include \"" + code.getLocality() + "\""
+ + System.getProperty("line.separator");
+ }
+
+ Sed sed = new Sed();
+ sed.sed(filename, "//#include \"@PROCESSNAME@.c\"", includes);
+ sed.sed(filename, "@PROCESSNAME@", p.getBasename());
+ sed.sed(filename, "@Processname@",
+ p.getBasename().substring(0, 1).toUpperCase() +
+ p.getBasename().substring(1));
+
+ String triggerPeriod = null;
+ String burstSize = null;
+ String burstPosition = null;
+ for (Configuration c : p.getCfgList()) {
+ if (c.getName().equals("triggerPeriod")) {
+ triggerPeriod = c.getValue();
+ } else if (c.getName().equals("burstSize")) {
+ burstSize = c.getValue();
+ } else if (c.getName().equals("burstPosition")) {
+ burstPosition = c.getValue();
+ }
+ }
+ if (triggerPeriod != null) {
+ if (burstSize == null) {
+ burstSize = "0";
+ }
+ if (burstPosition == null) {
+ burstPosition = "0";
+ }
+
+ String periodicTrigger =
+ "//limits the number of process activations\n"
+ + " while ((((int)get_cycle() - "
+ + "1511576) / " + triggerPeriod + ") "
+ + "< number_of_activations - (((int)get_cycle()"
+ // + " - 1511576) > " + burstPosition + " ? "
+ + " ) > " + burstPosition + " ? "
+ + burstSize + " : 0)) {\n"
+ + " rtems_task_set_priority("
+ + "RTEMS_SELF, 127, &old_priority);\n"
+ + " rtems_task_wake_after("
+ + "RTEMS_YIELD_PROCESSOR);\n"
+ + " }\n"
+ + " rtems_task_set_priority(RTEMS_SELF, "
+ + "wrapper->priority, &old_priority);\n";
+
+ sed.sed(filename,
+ "//placeholder for periodic trigger",
+ periodicTrigger);
+ }
+
+ if (!p.hasOutPorts()) {
+ sed.sed(filename, "@ENDING_SHAPER@",
+ "ss_sem_signal(get_sem_terminate("
+ + _sinkMap.get(p) + "));");
+ } else {
+ sed.sed(filename, "@ENDING_SHAPER@", "");
+ }
+
+ for(SourceCode sourceCode : p.getSrcList()) {
+ filename = _dir + _delimiter
+ + sourceCode.getLocality().replaceAll(
+ "(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+ sed.sed(filename, "<dol.h>", "\"dol.h\"");
+
+ for (Port port : p.getPortList()) {
+ Integer portId = _portMap.get(port);
+ if (!port.getBasename().equals(port.getName())) {
+ for (Port port2 : p.getPortList()) {
+ if (port2.getBasename().equals(port.getBasename())) {
+ if (_portMap.get(port2) < _portMap.get(port)) {
+ portId = _portMap.get(port2);
+ }
+ }
+ }
+ }
+ sed.sed(filename, "(#define[ ]+PORT_\\w*[ ]+)\"?"
+ + port.getBasename() + "\"?",
+ "$1 " + portId);
+ }
+ }
+ }
+ catch (Exception e) {
+ System.out.println("RtemsProcessVisitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ protected HashMap<Port, Integer> _portMap;
+ protected HashMap<Process, Integer> _sinkMap;
+}
--- /dev/null
+/* $Id: RtemsPropertiesVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.rtems;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import dol.datamodel.architecture.Architecture;
+import dol.datamodel.architecture.Processor;
+import dol.datamodel.mapping.Mapping;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.parser.xml.archischema.ArchiXmlParser;
+import dol.parser.xml.mapschema.MapXmlParser;
+import dol.visitor.PNVisitor;
+
+public class RtemsPropertiesVisitor extends PNVisitor {
+
+ protected String _dir = null;
+
+ public RtemsPropertiesVisitor(String dir) {
+ _dir = dir;
+ }
+
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "properties";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ ps.println(getProperties(x));
+ } catch (Exception e) {
+ System.out.println("RtemsPropertiesVisitor: "
+ + "exception occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public String getProperties(ProcessNetwork x) {
+ String file = "";
+ String newline = System.getProperty("line.separator");
+ file += "<!-- Properties for ANT script for "
+ + "Multi-Processor System Testbed -->" + newline;
+
+ int maxProcessorIndex;
+ String processorList = null;
+ String processList = null;
+
+ if (_ui.getMappingFileName() == null) {
+ maxProcessorIndex = x.getProcessList().size() - 1;
+ } else {
+ ArchiXmlParser architectureParser =
+ new ArchiXmlParser();
+ Architecture architecture = architectureParser.doParse(
+ _ui.getPlatformFileName());
+
+ MapXmlParser mappingParser =
+ new MapXmlParser(x, architecture);
+ Mapping mapping = mappingParser.doParse(
+ _ui.getMappingFileName());
+
+ maxProcessorIndex = 0;
+ for (Processor p : mapping.getProcessorList()) {
+ if (p.getProcessList().size() > 0) {
+ maxProcessorIndex =
+ Math.max(p.getIteratorIndices().elementAt(0),
+ maxProcessorIndex);
+ }
+ }
+ //maxProcessorIndex = mapping.getProcessorList().size() - 1;
+ }
+
+ processorList = "1";
+ for (int i = 1; i <= maxProcessorIndex; i++) {
+ processorList += "," + (i + 1);
+ }
+
+ for (Process p : x.getProcessList()) {
+ if (processList == null) {
+ processList = p.getName();
+ } else {
+ processList += "," + p.getName();
+ }
+ }
+
+
+ file += "processors=" + (maxProcessorIndex + 1) + newline;
+ file += "processorList=" + processorList + newline;
+ file += "processList=" + processList + newline;
+
+ return file;
+ }
+}
--- /dev/null
+/* $Id: RtemsShaperVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.rtems;
+
+import java.util.HashMap;
+
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a wrapper class for the traffic shaper.
+ */
+public class RtemsShaperVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir target directory
+ */
+ public RtemsShaperVisitor(String dir, HashMap<Process, Integer> sinkMap) {
+ _dir = dir;
+ _sinkMap = sinkMap;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be processed
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "traffic_shaping.h";
+
+ Sed sed = new Sed();
+ String tmp = "NUMBER_OF_QUEUES " + x.getChannelList().size();
+ sed.sed(filename, "@NUMBER_OF_QUEUES@", tmp);
+ tmp = "NUMBER_OF_SINKS " + _sinkMap.size();
+ sed.sed(filename, "@NUMBER_OF_SINKS@", tmp);
+ }
+ catch (Exception e) {
+ System.out.println("RtemsProcessVisitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ protected HashMap<Process, Integer> _sinkMap;
+}
--- /dev/null
+/* $Id: RtemsVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.rtems;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Vector;
+
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.Copier;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a RTEMS package.
+ */
+public class RtemsVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param packageName name of the Rtems directory
+ */
+ public RtemsVisitor(String packageName) {
+ _packageName = packageName;
+ }
+
+ /**
+ * Visit process network.
+ *
+ * @param pn process network that needs to be rendered.
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ //copy library files
+ File source = new File(_ui.getMySystemCLib().
+ replaceAll("systemC", "rtems"));
+ new Copier().copy(source, dir);
+
+ //copy process source code
+ source = new File(_srcDirName);
+ new Copier().copy(source, dir);
+
+ createPortMap(pn);
+ createSinkMap(pn);
+ pn.accept(new RtemsMakefileVisitor(_packageName));
+ pn.accept(new RtemsProcessVisitor(_packageName,_portMap,_sinkMap));
+ pn.accept(new RtemsModuleVisitor(_packageName, _portMap));
+ pn.accept(new RtemsShaperVisitor(_packageName, _sinkMap));
+ pn.accept(new RtemsPropertiesVisitor(_packageName));
+ }
+ catch (Exception e) {
+ System.out.println("RtemsVisitor: exception occured: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Create a hashmap which maps each port of the given process network
+ * to an integer. For each process, ports are numbered with integers
+ * starting from 0.
+ *
+ * @param pn process network for which the map should be generated
+ */
+ protected void createPortMap(ProcessNetwork pn) {
+ _portMap = new HashMap<Port, Integer>();
+
+ for (Process process : pn.getProcessList()) {
+ int portCount = 0;
+ Vector<Port> portList = process.getPortList();
+ Vector<String> portNameList = new Vector<String>();
+ portNameList.clear();
+ HashMap<String, Integer> portMap =
+ new HashMap<String, Integer>();
+ portMap.clear();
+
+ for (int i = 0; i < portList.size(); i++) {
+ //treat single ports differently than iterated ports
+ String portName = portList.elementAt(i).getName();
+ String baseName = portList.elementAt(i).getBasename();
+
+ if (portName.equals(baseName)) {
+ portNameList.add(portName);
+ portMap.put(portName, portCount++);
+ } else {
+ String range_indices = portList.elementAt(i).getRange();
+ Vector<Integer> range_indices_values = getIndex(range_indices, ";");
+
+ String port_indices = portName;
+ port_indices.replaceAll(baseName, "");
+ Vector<Integer> port_indices_values = getIndex(port_indices, "_");
+
+ if (!portNameList.contains(baseName)) {
+ portNameList.add(baseName);
+ portMap.put(baseName, portCount);
+
+ int size = 1;
+ for (int j = 0; j < range_indices_values.size(); j++) {
+ size *= range_indices_values.elementAt(j);
+ }
+ portCount += size;
+ }
+
+ int portId = portMap.get(baseName);
+ for (int j = 0; j < port_indices_values.size(); j++) {
+ int weight = 1;
+ for (int k = j + 1; k < range_indices_values.size(); k++) {
+ weight *= range_indices_values.elementAt(k);
+ }
+ portId += port_indices_values.elementAt(j) * weight;
+ }
+ portMap.put(portName, portId);
+ }
+ }
+
+ for (int i = 0; i < portList.size(); i++) {
+ _portMap.put(portList.elementAt(i),
+ portMap.get(portList.elementAt(i).getName()));
+ }
+ }
+ }
+
+
+ /**
+ * Create a hashmap which maps each sink of the given process network
+ * to an integer. For each process, sinks are numbered with integers
+ * starting from 1.
+ *
+ * @param pn process network for which the map should be generated
+ */
+ protected void createSinkMap(ProcessNetwork pn) {
+ _sinkMap = new HashMap<Process, Integer>();
+ int i = 1;
+
+ for (Process process : pn.getProcessList()) {
+ if (!process.hasOutPorts()) {
+ _sinkMap.put(process, i);
+ i++;
+ }
+ }
+ }
+
+ /**
+ * Gets vector of indices of a string, where the index must be
+ * separated by the specified separator.
+ * examples:
+ * getIndex("name_1_2", "_", 0) will return 1.
+ * getIndex("name_1_2", "_", 1) will return 2.
+ *
+ * @param range string to parse
+ * @param separator delimiter of indices
+ * @return vector of indices
+ */
+ protected Vector<Integer> getIndex(String range, String separator) {
+ Vector<Integer> indices = new Vector<Integer>();
+ String[] subranges = range.split(separator);
+ for (int i = 0; i < subranges.length; i++) {
+ try {
+ int value = Integer.valueOf(subranges[i]);
+ indices.add(value);
+ } catch (Exception e) {
+ continue;
+ }
+ }
+ return indices;
+ }
+
+ protected HashMap<Port, Integer> _portMap;
+ protected HashMap<Process, Integer> _sinkMap;
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+}
--- /dev/null
+How-to for running code in MPARM environment:
+
+One-to-one mapping:
+- Generate the code: ant -f runexample -Dnumber=? mparm
+- Copy the generated dir 'systemc' to <MPARM>/MPARM/apps
+- Copy the library 'queue_lib' into dir 'systemc'
+- Compile the code: make
+- Link the binary: ln -sf o-optimize/app.exe TargetMem_<?>.mem
+ ? depends on how many processors
+- Run: $SWARMDIR/bin/mpsim.x -c <?> --intc=i -C -S -D
+ ? is number of processors
+
+
+Multi-to-one mapping:
+- Modify main.c
+ - number_of_processes: each field is number of processes per processor
+ - xxx_PROCESSOR: set to a same number if mapping to common processor
+ - processor_init(): leave one for each processor (not necessary)
+- system.c
+ - macro CONFIGURE_MAXIMUM_TASKS should be two times larger than the
+ maximum number of processes mapped to one processor.
+- MAXQUEUE
+ - where should we put this macro ?
+- If using the dol mapping specification, the processor 1 should be reserved
+ in the case of enabling macro QUEUE_BUFF_SHAPER !
+
+MPARM queue_lib spec:
+- Always use interrupt
+- Always use memcpy
+- DMA always enables, the switch is in the Makefile
+- Token size is always 32 bits
+- Default Queue size is 4, can be redefined
+
+
+Segment wide Calibration:
+- Modify Makefile:
+ - enable macro PERFORMANCE_EXTRACT (default disable)
+ - uncomment line:
+ CXXSRCS += lib/xmlParser.cpp lib/Performance_Extraction.cpp
+- main.c: Map all processes into one processor
+- Run: $SWARMDIR/bin/mpsim.x -c 1 --intc=i -C -S -D
+
+
+Communication exploration:
+- Modify Makefile:
+ - enable one of below macro exclusively:
+ - QUEUE_BUFF_IN_PRODUCER (default)
+ - QUEUE_BUFF_IN_PRODUCER_DMA
+ - QUEUE_BUFF_IN_CONSUMER
+ - QUEUE_BUFF_IN_CONSUMER_DMA
+ - QUEUE_BUFF_SHAPER
+
+Running mpeg2 decoder on MPARM:
+- copy dol.h from other case studies
+- add macro _DOL_ETHZ_GEN_ to Makefile
+- change queue size to 4096 in system.h
+- call mpsim.x with option --s-size=19 (scratchpad size=1Mbyts)
+
+Running mjpeg-2000 decoder on MPARM:
+- jpeg.h
+ - disable macro VIEWER
+ - disable macros VERBOSE and INFO
+- scratch_queue.h
+ - macro MAXQUEUE > 24, if mapping all to one processor
+- system.h
+ - macro CONFIGURE_MAXIMUM_TASKS > 9
+
+
+Tricks:
+- CONFIGURE_MAXIMUM_TASKS in system.h
+- MAXQUEUE in scratch_queue.h
+- Token size should be multiple of 4 bytes
+- W/R operations should be the same size, otherwise token size should be
+ gcd(Write_token, Read_token).
+
+BUGS & TODO:
+- free() in wrapper not correct
+- Iterated port not tested yet
+- Shaper not finished!
+- Timeslice works? (Yes)
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+// Copyright 2003 DEIS - Universita' di Bologna\r
+//\r
+// name appsupport.c\r
+// author DEIS - Universita' di Bologna\r
+// Davide Bertozzi - dbertozzi@deis.unibo.it\r
+// Mirko Loghi - mloghi@deis.unibo.it\r
+// Federico Angiolini - fangiolini@deis.unibo.it\r
+// Francesco Poletti - fpoletti@deis.unibo.it\r
+// portions by Massimo Scardamaglia - mascard@vizzavi.it\r
+// info Provides support for testbench compilation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+#include <bsp.h>\r
+\r
+#include "appsupport.h"\r
+\r
+volatile char *time_low_ptr = (char *)(SIMSUPPORT_BASE + GET_TIME_ADDRESS_LO);\r
+volatile char *time_high_ptr = (char *)(SIMSUPPORT_BASE + GET_TIME_ADDRESS_HI);\r
+volatile char *time_stop_ptr = (char *)(SIMSUPPORT_BASE + STOP_TIME_ADDRESS);\r
+volatile char *time_rel_ptr = (char *)(SIMSUPPORT_BASE + RELEASE_TIME_ADDRESS);\r
+\r
+volatile char *cycle_low_ptr = (char *)(SIMSUPPORT_BASE + GET_CYCLE_ADDRESS_LO);\r
+volatile char *cycle_high_ptr = (char *)(SIMSUPPORT_BASE + GET_CYCLE_ADDRESS_HI);\r
+volatile char *cycle_stop_ptr = (char *)(SIMSUPPORT_BASE + STOP_CYCLE_ADDRESS);\r
+volatile char *cycle_rel_ptr = (char *)(SIMSUPPORT_BASE + RELEASE_CYCLE_ADDRESS);\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// pr - Allows printing debug info even without support from an OS. See\r
+// user_swi.cpp for printable messages, or to create your own\r
+\r
+void pr(int proc, int msg_num, int num_arg)\r
+{\r
+#ifndef __OPTIMIZE__\r
+ __asm ("ldr r1, %0" : : "g" (proc) : "r1" );\r
+ __asm ("ldr r2, %0" : : "g" (msg_num) : "r2" );\r
+ __asm ("ldr r3, %0" : : "g" (num_arg) : "r3" );\r
+ __asm ("swi " SWI_PRINTstr);\r
+#else\r
+ __asm ("mov r1, %0" : : "g" (proc) : "r1" );\r
+ __asm ("mov r2, %0" : : "g" (msg_num) : "r2" );\r
+ __asm ("mov r3, %0" : : "g" (num_arg) : "r3" );\r
+ __asm ("swi " SWI_PRINTstr);\r
+#endif\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// get_proc_id - Allows getting the processor's ID (from 1 onwards)\r
+unsigned int get_proc_id()\r
+{\r
+ char *ptr = (char *)(SIMSUPPORT_BASE + GET_CPU_ID_ADDRESS);\r
+ return (*(unsigned long int *)ptr);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// get_proc_num - Allows getting the number of processors in the platform\r
+unsigned int get_proc_num()\r
+{\r
+ char *ptr = (char *)(SIMSUPPORT_BASE + GET_CPU_CNT_ADDRESS);\r
+ return (*(unsigned long int *)ptr);\r
+}\r
+\r
+// ---------------------------\r
+// Frequency scaling functions\r
+// ---------------------------\r
+volatile unsigned int *freqdevice = (unsigned int *)FREQ_BASE;\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// scale_this_core_frequency - Scales the frequency of the core on which\r
+// the application is running\r
+void scale_this_core_frequency(unsigned short int divider)\r
+{\r
+ freqdevice[get_proc_id() - 1] = divider;\r
+}\r
+///////////////////////////////////////////////////////////////////////////////\r
+// scale_device_frequency - Scales the frequency of any device in the system\r
+void scale_device_frequency(unsigned short int divider, int ID)\r
+{\r
+ freqdevice[ID] = divider;\r
+}\r
+///////////////////////////////////////////////////////////////////////////////\r
+// get_this_core_frequency - Gets the frequency divider of the core on which\r
+// the application is running\r
+unsigned short int get_this_core_frequency()\r
+{\r
+ return (freqdevice[get_proc_id() - 1]);\r
+}\r
+///////////////////////////////////////////////////////////////////////////////\r
+// get_device_frequency - Gets the frequency divider of any device in the system\r
+unsigned short int get_device_frequency(int ID)\r
+{\r
+ return (freqdevice[ID]);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// get_time - Allows getting the current simulation time\r
+unsigned long long int get_time()\r
+{\r
+ unsigned long long int time;\r
+ \r
+ *time_stop_ptr = 1;\r
+ time = (((unsigned long long int)(*(unsigned long int *)time_high_ptr)) << 32) + *(unsigned long int *)time_low_ptr;\r
+ *time_rel_ptr = 1;\r
+ \r
+ return (time);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////////\r
+// get_cycle - Allows getting the current simulation cycle\r
+unsigned long long int get_cycle1()\r
+{\r
+ unsigned long long int cycle;\r
+ \r
+ *cycle_stop_ptr = 1;\r
+ cycle = (((unsigned long long int)(*(unsigned long int *)cycle_high_ptr)) << 32) + *(unsigned long int *)cycle_low_ptr;\r
+ *cycle_rel_ptr = 1;\r
+ \r
+ return (cycle);\r
+}\r
+\r
+extern rtems_id timer_sem_id;\r
+unsigned long long int get_cycle()\r
+{\r
+ unsigned long long int cycle;\r
+ rtems_status_code rtems_status;\r
+\r
+ rtems_status = rtems_semaphore_obtain(timer_sem_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);\r
+ *cycle_stop_ptr = 1;\r
+ cycle = (((unsigned long long int)(*(unsigned long int *)cycle_high_ptr))\r
+ << 32) + *(unsigned long int *)cycle_low_ptr;\r
+ *cycle_rel_ptr = 1;\r
+ rtems_status = rtems_semaphore_release(timer_sem_id);\r
+\r
+ return (cycle);\r
+}\r
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////\r
+// Copyright 2003 DEIS - Universita' di Bologna\r
+// \r
+// name appsupport.h\r
+// author DEIS - Universita' di Bologna\r
+// Davide Bertozzi - dbertozzi@deis.unibo.it\r
+// Mirko Loghi - mloghi@deis.unibo.it\r
+// Federico Angiolini - fangiolini@deis.unibo.it\r
+// Francesco Poletti - fpoletti@deis.unibo.it\r
+// portions by Massimo Scardamaglia - mascard@vizzavi.it\r
+// info Provides support for testbench compilation\r
+//\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef __APPSUPPORT_H__\r
+#define __APPSUPPORT_H__\r
+\r
+#include "swi_calls.h"\r
+#include "config.h"\r
+#include "sim_support_flags.h"\r
+\r
+#define start_metric() __asm ("swi " SWI_METRIC_STARTstr)\r
+#define stop_metric() __asm ("swi " SWI_METRIC_STOPstr)\r
+#define dump_metric() __asm ("swi " SWI_METRIC_DUMPstr)\r
+#define clear_metric() __asm ("swi " SWI_METRIC_CLEARstr)\r
+#define stop_simulation() __asm ("swi " SWI_EXITstr)\r
+void pr(int proc, int msg_num, int num_arg);\r
+unsigned int get_proc_id();\r
+\r
+#undef get_id\r
+#define get_id() get_proc_id()\r
+\r
+unsigned int get_proc_num();\r
+\r
+// ---------------------------\r
+// Frequency scaling functions\r
+// ---------------------------\r
+void scale_this_core_frequency(unsigned short int divider);\r
+void scale_device_frequency(unsigned short int divider, int ID);\r
+unsigned short int get_this_core_frequency();\r
+unsigned short int get_device_frequency(int ID);\r
+\r
+#define RTEMS_TRACE_MAIN_APP\r
+\r
+#ifdef RTEMS_TRACE_MAIN_APP\r
+//It print out the processor id, the parameter "a" and the actual clock cycles\r
+//Eg. Processor 0 - 0x3e740 start_cycle:353089\r
+#define SHOW_TIME_START(a) pr(0x11111, 0x10020, (int)a)\r
+//Eg. Processor 0 - 0x3e740 stop_cycle:353143\r
+#define SHOW_TIME_STOP(a) pr(0x11111, 0x10030, (int)a)\r
+//It print out the string a \r
+#define SHOW_DEBUG(a) pr(0x11111, 0x10000, (int)a)\r
+#define SHOW_DEBUG_NON(a) pr(0x11111, 0x10001, (int)a)\r
+#define SHOW_DEBUG_NOP(a) pr(0x11111, 0x10002, (int)a)\r
+#define SHOW_DEBUG_NON_NOP(a) pr(0x11111, 0x10003, (int)a)\r
+//It print out the integer a\r
+#define SHOW_DEBUG_INT(a) pr(0x11111, 0x10010, (int)a)\r
+#define SHOW_DEBUG_INT_NON(a) pr(0x11111, 0x10011, (int)a)\r
+#define SHOW_DEBUG_INT_NOP(a) pr(0x11111, 0x10012, (int)a)\r
+#define SHOW_DEBUG_INT_NON_NOP(a) pr(0x11111, 0x10013, (int)a)\r
+#else\r
+//empty definitions\r
+#define SHOW_TIME_START(a)\r
+#define SHOW_TIME_STOP(a)\r
+#define SHOW_DEBUG(a)\r
+#define SHOW_DEBUG_NON(a)\r
+#define SHOW_DEBUG_INT_NOP(a)\r
+#define SHOW_DEBUG_INT_NON_NOP(a)\r
+#define SHOW_DEBUG_INT(a)\r
+#define SHOW_DEBUG_INT_NON(a)\r
+#define SHOW_DEBUG_INT_NOP(a)\r
+#define SHOW_DEBUG_INT_NON_NOP(a)\r
+#endif\r
+\r
+unsigned long long int get_time();\r
+unsigned long long int get_cycle();\r
+unsigned long long int get_cycle1();\r
+\r
+#endif // __APPSUPPORT_H__\r
--- /dev/null
+/*
+ * Support for running the test output through a buffer
+ *
+ * buffer_test_io.h,v 1.1 2002/08/02 00:51:52 joel Exp
+ */
+
+#ifndef __BUFFER_TEST_IO_h
+#define __BUFFER_TEST_IO_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+/*
+ * Uncomment this to get buffered test output. When commented out,
+ * test output behaves as it always has and is printed ASAP.
+ */
+
+/* #define TESTS_BUFFER_OUTPUT */
+
+#if !defined(TESTS_BUFFER_OUTPUT)
+
+#define rtems_test_exit(_s) \
+ do { \
+ exit(_s); \
+ } while (0)
+
+#define FLUSH_OUTPUT() \
+ do { \
+ fflush(stdout); \
+ } while (0)
+
+#else /* buffer test output */
+
+#define _TEST_OUTPUT_BUFFER_SIZE 2048
+extern char _test_output_buffer[_TEST_OUTPUT_BUFFER_SIZE];
+void _test_output_append(char *);
+void _test_output_flush(void);
+
+#define rtems_test_exit(_s) \
+ do { \
+ _test_output_flush(); \
+ exit(_s); \
+ } while (0)
+
+#undef printf
+#define printf(...) \
+ do { \
+ char _buffer[128]; \
+ sprintf( _buffer, __VA_ARGS__); \
+ _test_output_append( _buffer ); \
+ } while (0)
+
+#undef puts
+#define puts(_string) \
+ do { \
+ char _buffer[128]; \
+ sprintf( _buffer, "%s\n", _string ); \
+ _test_output_append( _buffer ); \
+ } while (0)
+
+#undef putchar
+#define putchar(_c) \
+ do { \
+ char _buffer[2]; \
+ _buffer[0] = _c; \
+ _buffer[1] = '\0'; \
+ _test_output_append( _buffer ); \
+ } while (0)
+
+/* we write to stderr when there is a pause() */
+#define FLUSH_OUTPUT() _test_output_flush()
+
+#if defined(TEST_INIT) || defined(CONFIGURE_INIT)
+
+char _test_output_buffer[_TEST_OUTPUT_BUFFER_SIZE];
+int _test_output_buffer_index = 0;
+
+void _test_output_append(char *_buffer)
+{
+ char *p;
+
+ for ( p=_buffer ; *p ; p++ ) {
+ _test_output_buffer[_test_output_buffer_index++] = *p;
+ _test_output_buffer[_test_output_buffer_index] = '\0';
+#if 0
+ if ( *p == '\n' ) {
+ fprintf( stderr, "BUFFER -- %s", _test_output_buffer );
+ _test_output_buffer_index = 0;
+ _test_output_buffer[0] = '\0';
+ }
+#endif
+ if ( _test_output_buffer_index >= (_TEST_OUTPUT_BUFFER_SIZE - 80) )
+ _test_output_flush();
+ }
+}
+
+#include <termios.h>
+#include <unistd.h>
+
+void _test_output_flush(void)
+{
+ fprintf( stderr, "%s", _test_output_buffer );
+ _test_output_buffer_index = 0;
+ tcdrain( 2 );
+}
+
+#endif /* TEST_INIT */
+#endif /* TESTS_BUFFER_OUTPUT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+#ifndef __DOL_H__
+#define __DOL_H__
+
+//structure for local memory of process
+typedef struct _local_states *LocalState;
+
+//structure for process
+struct _process;
+
+//
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr;
+} DOLProcess;
+
+void DOL_read(void *port, void *buf, int len, DOLProcess *process);
+void DOL_write(void *port, void *buf, int len, DOLProcess *process);
+void DOL_detach(DOLProcess *process);
+
+#endif
--- /dev/null
+#include <bsp.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rtems_process_wrapper.h"
+
+#ifdef WORKLOAD_EXTRACT
+#define DOL_read(port, buf, len, process) \
+{ ((RtemsProcessWrapper*)process->wptr)->end_line = __LINE__; \
+ DOL_read(port, buf, len, process); \
+ ((RtemsProcessWrapper*)process->wptr)->start_line = __LINE__; }
+
+#define DOL_write(port, buf, len, process) \
+{ ((RtemsProcessWrapper*)process->wptr)->end_line = __LINE__; \
+ DOL_write(port, buf, len, process); \
+ ((RtemsProcessWrapper*)process->wptr)->start_line = __LINE__; }
+#endif
+
+#ifdef PRINTF_TO_DEBUG
+#undef printf
+#define printf(...) \
+ do { \
+ char _buffer[128]; \
+ sprintf(_buffer, __VA_ARGS__); \
+ SHOW_DEBUG((int)_buffer); \
+ } while (0)
+#endif
+
+//#include "@PROCESSNAME@.c"
+
+//DOL-specific implementation
+rtems_task @PROCESSNAME@_task(rtems_task_argument argument) {
+ RtemsProcessWrapper* wrapper = (RtemsProcessWrapper*)argument;
+ DOLProcess* process;
+ LocalState state;
+ int number_of_activations = 0;
+ int i;
+ rtems_task_priority old_priority;
+
+ process = (DOLProcess *)malloc(sizeof(DOLProcess));
+ state = (LocalState)malloc(sizeof(@Processname@_State));
+ process->init = @PROCESSNAME@_init;
+ process->fire = @PROCESSNAME@_fire;
+ process->local = state;
+ process->wptr = wrapper;
+
+ //initialize the index array
+ wrapper->index = (int *)malloc(4 * sizeof(int));
+ for (i = 0; i < 4; i++) {
+ wrapper->index[i] = getIndex(wrapper->name, "_", i);
+ }
+
+ printf("Start process %s.\n", wrapper->name);
+ process->init(process);
+
+ //yield process such that other processes can be initialized
+#ifdef MPARM
+ do {
+ rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
+ } while((int)get_cycle() < 1511576);
+#endif
+ rtems_task_set_priority(RTEMS_SELF, wrapper->priority, &old_priority);
+
+ while (!wrapper->is_detached) {
+
+ //placeholder for periodic trigger
+
+#ifdef WORKLOAD_EXTRACT
+ wrapper->start_line = 0;
+ SHOW_DEBUG("log start_fire");
+ SHOW_DEBUG_INT((int)get_cycle());
+#endif
+
+ process->fire(process);
+
+#ifdef WORKLOAD_EXTRACT
+ SHOW_DEBUG("log end_fire");
+ SHOW_DEBUG_INT((int)get_cycle());
+ wrapper->end_line = 0;
+#endif
+ number_of_activations++;
+ }
+
+#ifdef MPARM_SCRATCHPAD_QUEUE
+ #ifdef QUEUE_BUFF_SHAPER
+ @ENDING_SHAPER@
+ #endif
+#else // pc386
+ //below is not necessary if no dynamic switching
+ //printf("Detached @PROCESSNAME@. Cleanup... ");
+ if (wrapper->index) {
+ free(wrapper->index);
+ } else {
+ printf("Could not free memory for index of @PROCESSNAME@.\n");
+ }
+
+ if (wrapper->port_id) {
+ free(wrapper->port_id);
+ } else {
+ printf("Could not free memory for port_id of @PROCESSNAME@.\n");
+ }
+
+ if (wrapper->port_queue_id) {
+ } else {
+ printf("Could not free memory for port_queue_id of @PROCESSNAME@.\n");
+ }
+#endif // MPARM_SCRATCHPAD_QUEUE
+ //printf("Done.\n");
+
+ printf("Detach process %s.\n", wrapper->name);
+#ifdef MPARM
+ Cleanup();
+#endif
+
+ rtems_task_delete(RTEMS_SELF);
+}
--- /dev/null
+#include <string.h>
+#include "rtems_process_wrapper.h"
+
+/**
+ *
+ */
+void DOL_read(void *port, void *buf, int len, DOLProcess *process) {
+ RtemsProcessWrapper* process_wrapper = (RtemsProcessWrapper*)process->wptr;
+ int i;
+
+#ifdef WORKLOAD_EXTRACT
+ SHOW_DEBUG("log start_read");
+ SHOW_DEBUG_INT((int)get_cycle());
+ SHOW_DEBUG_INT((int)port);
+ SHOW_DEBUG_INT((int)(process_wrapper->start_line));
+ SHOW_DEBUG_INT((int)(process_wrapper->end_line));
+ SHOW_DEBUG_INT((int)len);
+#endif
+
+#ifdef MPARM_SCRATCHPAD_QUEUE
+ for (i = 0; i < process_wrapper->number_of_in_ports; i++) {
+ // len not taken into account yet !!!!!!!
+ if (process_wrapper->in_port_id[i] == (int)port) {
+ SCRATCH_QUEUE_CONSUMER* queue_id =
+ (SCRATCH_QUEUE_CONSUMER*)process_wrapper->in_queue_id[i];
+
+#if defined (QUEUE_BUFF_IN_PRODUCER)
+ scratch_queue_read(queue_id, (char *)buf, len);
+#elif defined (QUEUE_BUFF_IN_PRODUCER_DMA)
+ scratch_queue_read_dma(queue_id, (char *)buf, len);
+#elif defined (QUEUE_BUFF_IN_CONSUMER)
+ scratch_queue_read(queue_id, (char *)buf, len);
+#elif defined (QUEUE_BUFF_IN_CONSUMER_DMA)
+ scratch_queue_read(queue_id, (char *)buf, len);
+#elif defined (QUEUE_BUFF_IN_SHARDMEM)
+ scratch_queue_read(queue_id, (char *)buf, len);
+#elif defined (QUEUE_BUFF_SHAPER)
+ scratch_queue_read_2(queue_id, (char *)buf, len);
+#endif
+ break;
+ }
+ }
+#else // pc386
+ for (i = 0; i < process_wrapper->number_of_ports; i++) {
+ if (process_wrapper->port_id[i] == (int)port) {
+ int queue_id = process_wrapper->port_queue_id[i];
+ int j;
+
+ //receive message byte-per-byte
+ for (j = 0; j < len; j++) {
+ size_t size = 1;
+ rtems_message_queue_receive(
+ queue_id,
+ buf + j,
+ &size,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ RTEMS_NO_TIMEOUT);
+ }
+ break;
+ }
+ }
+#endif // end MPARM_SCRATCHPAD_QUEUE
+
+ //SHOW_DEBUG("read from app");
+ //SHOW_DEBUG_INT(*(int *)buf);
+
+#ifdef WORKLOAD_EXTRACT
+ SHOW_DEBUG("log end_read");
+ SHOW_DEBUG_INT((int)get_cycle());
+ SHOW_DEBUG_INT((int)port);
+#endif
+}
+
+/**
+ *
+ */
+void DOL_write(void *port, void *buf, int len, DOLProcess *process) {
+ RtemsProcessWrapper* process_wrapper = (RtemsProcessWrapper*)process->wptr;
+ int i;
+
+#ifdef WORKLOAD_EXTRACT
+ SHOW_DEBUG("log start_write");
+ SHOW_DEBUG_INT((int)get_cycle());
+ SHOW_DEBUG_INT((int)port);
+ SHOW_DEBUG_INT((int)(process_wrapper->start_line));
+ SHOW_DEBUG_INT((int)(process_wrapper->end_line));
+ SHOW_DEBUG_INT((int)len);
+#endif
+
+#if defined MPARM_SCRATCHPAD_QUEUE
+ for (i = 0; i < process_wrapper->number_of_out_ports; i++) {
+ if (process_wrapper->out_port_id[i] == (int)port) {
+ SCRATCH_QUEUE_PRODUCER* queue_id =
+ (SCRATCH_QUEUE_PRODUCER*)process_wrapper->out_queue_id[i];
+
+
+#if defined (QUEUE_BUFF_IN_PRODUCER) || (QUEUE_BUFF_IN_CONSUMER)
+ scratch_queue_write(queue_id, (char *)buf, len);
+#elif defined (QUEUE_BUFF_IN_PRODUCER_DMA) || (QUEUE_BUFF_IN_CONSUMER_DMA)
+ scratch_queue_write_dma(queue_id, (char *)buf, len);
+#elif defined (QUEUE_BUFF_IN_SHARDMEM)
+ scratch_queue_write(queue_id, (char *)buf, len);
+#elif defined(QUEUE_BUFF_SHAPER)
+ scratch_queue_write_2(queue_id, (char *)buf, len); // (2) shaper
+#endif
+
+ break;
+ }
+ }
+#else // pc386
+ for (i = 0; i < process_wrapper->number_of_ports; i++) {
+ if (process_wrapper->port_id[i] == (int)port) {
+ int queue_id = process_wrapper->port_queue_id[i];
+ rtems_status_code status;
+ int j;
+
+ //send message byte-per-byte
+ for (j = 0; j < len; j++) {
+ do {
+ status = rtems_message_queue_send(queue_id, buf + j, 1);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_task_wake_after(0);
+ }
+ } while (status != RTEMS_SUCCESSFUL);
+ }
+
+ break;
+ }
+ }
+#endif // end MPARM_SCRATCHPAD_QUEUE
+
+#ifdef WORKLOAD_EXTRACT
+ SHOW_DEBUG("log end_write");
+ SHOW_DEBUG_INT((int)get_cycle());
+ SHOW_DEBUG_INT((int)port);
+#endif
+}
+
+/**
+ *
+ */
+void DOL_detach(DOLProcess *process) {
+ //printf("[%s] DOL_detach.\n", (char*)(process->local));
+ ((RtemsProcessWrapper*)process->wptr)->is_detached = 1;
+}
+
+/**
+ * Gets an index of a string, where the index must be separated by
+ * a character specified in tokens.
+ * Returns -1, when an error occurs.
+ *
+ * Example:
+ * getIndex("name_1_2", "_", 0) will return 1.
+ * getIndex("name_1_2", "_", 1) will return 2.
+ *
+ * @param string string to parse
+ * @param tokens delimiter of indices
+ * @param indexNumber position of index (starting at 0)
+ */
+int getIndex(const char* string, char* tokens, int indexNumber) {
+ char* string_copy;
+ char* token_pointer;
+ int index = 0;
+
+ string_copy = (char*) malloc(sizeof(char) * (strlen(string) + 1));
+ if (!string_copy) {
+ fprintf(stderr, "getIndex(): could not allocate memory.\n");
+ return -1;
+ }
+
+ strcpy(string_copy, string);
+
+ token_pointer = strtok(string_copy, tokens);
+ do {
+ token_pointer = strtok(NULL, tokens);
+ index++;
+ } while (index <= indexNumber && token_pointer != 0);
+
+ if (token_pointer) {
+ index = atoi(token_pointer);
+ free(string_copy);
+ return index;
+ }
+
+ free(string_copy);
+ return -1;
+}
+
+/**
+ * Create the port name of an iterated port based on its basename and the
+ * given indices.
+ *
+ * @param port buffer where the result is stored (created using
+ * CREATEPORTVAR)
+ * @param base basename of the port
+ * @param number_of_indices number of dimensions of the port
+ * @param index_range_pairs index and range values for each dimension
+ */
+int *createPort(int *port, int base, int number_of_indices,
+ int index_range_pairs, ...) {
+ int index[4];
+ int range[4];
+ int i;
+ int value;
+
+ va_list marker;
+ va_start(marker, index_range_pairs);
+
+ value = index_range_pairs;
+ for (i = 0; i < number_of_indices; i++) {
+ index[i] = value;
+ value = va_arg(marker, int);
+ range[i] = value;
+ if (i < number_of_indices - 1) {
+ value = va_arg(marker, int);
+ }
+ }
+
+ *port = base;
+ for (i = 0; i < number_of_indices; i++) {
+ int j;
+ int weight = 1;
+ for (j = 1; j < number_of_indices - i; j ++) {
+ weight *= range[j];
+ }
+ *port += index[i] * weight;
+ }
+
+ /*
+ switch (number_of_indices) {
+ case 1:
+ *port = base + index[0];
+ break;
+ case 2:
+ *port = base + index[0] * range[1]
+ + index[1];
+ break;
+ case 3:
+ *port = base + index[0] * range[1] * range[2]
+ + index[1] * range[0]
+ + index[2];
+ break;
+ case 4:
+ *port = base + index[0] * range[1] * range[2] * range[3]
+ + index[1] * range[2] * range[3]
+ + index[2] * range[3]
+ + index[3];
+ break;
+ }
+ */
+
+ return port;
+}
--- /dev/null
+#ifndef __RTEMS_PROCESS_WRAPPER_H__
+#define __RTEMS_PROCESS_WRAPPER_H__
+
+#include <bsp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "dol.h"
+
+#ifdef MPARM_SCRATCHPAD_QUEUE
+#include "scratch_queue.h"
+#endif
+
+#ifdef MPARM
+#define printf(format ...) { char stringBuffer[80]; sprintf(stringBuffer, format); SHOW_DEBUG(stringBuffer); }
+#endif
+
+typedef struct _process_wrapper {
+ DOLProcess *dol_process;
+ char* name;
+ int* index;
+ int is_detached;
+ int priority;
+#ifdef WORKLOAD_EXTRACT
+ int start_line;
+ int end_line;
+#endif
+#ifdef MPARM_SCRATCHPAD_QUEUE
+ int* in_port_id;
+ int* out_port_id;
+ SCRATCH_QUEUE_PRODUCER** out_queue_id;
+ SCRATCH_QUEUE_CONSUMER** in_queue_id;
+ int number_of_in_ports;
+ int number_of_out_ports;
+#else // for pc396
+ int* port_id;
+ int* port_queue_id;
+ int number_of_ports;
+#endif
+} RtemsProcessWrapper;
+
+// define queue memory in consumer scratchpad
+//#define QUEUE_IN_CONSUMER
+
+/**
+ * Gets an index of a string, where the index must be separated by
+ * a character specified in tokens.
+ * Returns -1, when an error occurs.
+ *
+ * Example:
+ * getIndex("name_1_2", "_", 0) will return 1.
+ * getIndex("name_1_2", "_", 1) will return 2.
+ *
+ * @param string string to parse
+ * @param tokens delimiter of indices
+ * @param indexNumber position of index (starting at 0)
+ */
+int getIndex(const char* string, char* tokens, int indexNumber);
+
+/**
+ * Create the port name of an iterated port based on its basename and the
+ * given indices.
+ *
+ * @param port buffer where the result is stored (created using
+ * CREATEPORTVAR)
+ * @param base basename of the port
+ * @param number_of_indices number of dimensions of the port
+ * @param index_range_pairs index and range values for each dimension
+ */
+int *createPort(int *port, int base, int number_of_indices, int index_range_pairs, ...);
+
+//DOL macros
+#define GETINDEX(dimension) \
+ ((RtemsProcessWrapper*)(p->wptr))->index[dimension]
+
+#define CREATEPORTVAR(name) \
+ int name
+
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \
+ createPort(&port, base, number_of_indices, index_range_pairs)
+
+#ifdef PERFORMANCE_EXTRACT
+#include "Performance_Extraction.h"
+#endif
+
+#ifdef MPARM
+extern unsigned int active_processes;
+inline void Cleanup() {
+ register rtems_interrupt_level level;
+ rtems_interrupt_disable(level);
+ active_processes--;
+
+ if(active_processes==0) {
+#ifdef PERFORMANCE_EXTRACT
+ performance_extraction.write_to_xml_file("calibration");
+#endif
+ printf("All processes detached.");
+ rtems_interrupt_enable(level);
+ exit(0);
+ }
+ rtems_interrupt_enable(level);
+}
+#endif
+
+#endif
--- /dev/null
+/* system.h
+ *
+ * This include file contains information that is included in every
+ * function in the test set.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * system.h,v 1.12 2000/06/12 15:00:11 joel Exp
+ */
+
+#include "tmacros.h"
+#include "appsupport.h"
+
+// Functions
+rtems_task Init(rtems_task_argument argument);
+rtems_task Test_task(rtems_task_argument argument);
+
+// Configuration information
+#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
+
+#define MAXIMUM_REGIONS 2
+
+#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 4
+
+// Tells confdefs.h to build the init task configuration
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+// ??????
+#define CONFIGURE_TICKS_PER_TIMESLICE 100 // ???
+
+#define CONFIGURE_MAXIMUM_TASKS 32
+
+// Tells confdefs.h to build the default configuration table
+#ifdef TEST_INIT
+#define CONFIGURE_INIT
+#endif
+
+#define CONFIGURE_MP_APPLICATION
+//These are just to allow the OS to be able to compile.
+//Then this value is overwritten during the boot of the OS,
+//using the call to coprocessor functions
+#define CONFIGURE_MP_MAXIMUM_NODES 1
+#define NODE_NUMBER 1
+
+
+/////////////////////////////////
+#define SCRATCHPAD_QUEUE // enable scratchpad queue
+
+#define DEFAULT_BUFFER_SIZE 100 //scratchpad queue size
+#define TOKEN_BYTES 4096
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES 2
+
+//#define MAXQUEUE 10
+//#define SCRATCH_SIZE_PLATFORM (1024*512)
+
+
+
+#include <confdefs.h>
+
--- /dev/null
+/* tmacros.h
+ *
+ * This include file contains macros which are useful in the RTEMS
+ * test suites.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * tmacros.h,v 1.25 2002/08/02 00:51:52 joel Exp
+ */
+
+#ifndef __TMACROS_h
+#define __TMACROS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <bsp.h> /* includes <rtems.h> */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <rtems/error.h>
+
+#define FOREVER 1 /* infinite loop */
+
+#ifdef TEST_INIT
+#define TEST_EXTERN
+#else
+#define TEST_EXTERN extern
+#endif
+
+#include "buffer_test_io.h"
+
+/*
+ * Check that that the dispatch disable level is proper for the
+ * mode/state of the test. Normally it should be 0 when in task space.
+ */
+
+#define check_dispatch_disable_level( _expect ) \
+ do { \
+ extern volatile rtems_unsigned32 _Thread_Dispatch_disable_level; \
+ if ( (_expect) != -1 && _Thread_Dispatch_disable_level != (_expect) ) { \
+ printf( "\n_Thread_Dispatch_disable_level is (%d) not %d\n", \
+ _Thread_Dispatch_disable_level, (_expect) ); \
+ FLUSH_OUTPUT(); \
+ rtems_test_exit( 1 ); \
+ } \
+ } while ( 0 )
+
+/*
+ * These macros properly report errors within the Classic API
+ */
+
+#define directive_failed( _dirstat, _failmsg ) \
+ fatal_directive_status( _dirstat, RTEMS_SUCCESSFUL, _failmsg )
+
+#define directive_failed_with_level( _dirstat, _failmsg, _level ) \
+ fatal_directive_status_with_level( \
+ _dirstat, RTEMS_SUCCESSFUL, _failmsg, _level )
+
+#define fatal_directive_status( _stat, _desired, _msg ) \
+ fatal_directive_status_with_level( _stat, _desired, _msg, 0 )
+
+#define fatal_directive_check_status_only( _stat, _desired, _msg ) \
+ do { \
+ if ( (_stat) != (_desired) ) { \
+ printf( "\n%s FAILED -- expected (%s) got (%s)\n", \
+ (_msg), rtems_status_text(_desired), rtems_status_text(_stat) ); \
+ FLUSH_OUTPUT(); \
+ rtems_test_exit( _stat ); \
+ } \
+ } while ( 0 )
+
+#define fatal_directive_status_with_level( _stat, _desired, _msg, _level ) \
+ do { \
+ check_dispatch_disable_level( _level ); \
+ fatal_directive_check_status_only( _stat, _desired, _msg ); \
+ } while ( 0 )
+
+/*
+ * These macros properly report errors from the POSIX API
+ */
+
+#define posix_service_failed( _dirstat, _failmsg ) \
+ fatal_posix_service_status( _dirstat, RTEMS_SUCCESSFUL, _failmsg )
+
+#define posix_service_failed_with_level( _dirstat, _failmsg, _level ) \
+ fatal_posix_service_status_with_level( \
+ _dirstat, RTEMS_SUCCESSFUL, _failmsg, _level )
+
+#define fatal_posix_service_status( _stat, _desired, _msg ) \
+ fatal_posix_service_status_with_level( _stat, _desired, _msg, 0 )
+
+#define fatal_posix_service_status_with_level( _stat, _desired, _msg, _level ) \
+ do { \
+ check_dispatch_disable_level( _level ); \
+ if ( (_stat) != (_desired) ) { \
+ printf( "\n%s FAILED -- expected (%d - %s) got (%d - %s)\n", \
+ (_msg), _desired, strerror(_desired), _stat, strerror(_stat) ); \
+ printf( "\n FAILED -- errno (%d - %s)\n", \
+ errno, strerror(errno) ); \
+ FLUSH_OUTPUT(); \
+ rtems_test_exit( _stat ); \
+ } \
+ } while ( 0 )
+
+/*
+ * Generic integer version of the error reporting
+ */
+
+#define int_service_failed( _dirstat, _failmsg ) \
+ fatal_int_service_status( _dirstat, RTEMS_SUCCESSFUL, _failmsg )
+
+#define int_service_failed_with_level( _dirstat, _failmsg, _level ) \
+ fatal_int_service_status_with_level( \
+ _dirstat, RTEMS_SUCCESSFUL, _failmsg, _level )
+
+#define fatal_int_service_status( _stat, _desired, _msg ) \
+ fatal_int_service_status_with_level( _stat, _desired, _msg, 0 )
+
+#define fatal_int_service_status_with_level( _stat, _desired, _msg, _level ) \
+ do { \
+ check_dispatch_disable_level( _level ); \
+ if ( (_stat) != (_desired) ) { \
+ printf( "\n%s FAILED -- expected (%d) got (%d)\n", \
+ (_msg), (_desired), (_stat) ); \
+ FLUSH_OUTPUT(); \
+ rtems_test_exit( _stat ); \
+ } \
+ } while ( 0 )
+
+/*
+ * Print the time: modificata per swarm da Poletti Francesco per risolvere il
+ * problema di stampa degli interi
+ */
+
+#define print_time(_s1, _tb, _s2) \
+ do { \
+ myprint( "%s%02d:%02d:%02d %02d/%02d/%0d%s", \
+ _s1, (_tb)->hour, (_tb)->minute, (_tb)->second, \
+ (_tb)->month, (_tb)->day, (_tb)->year, _s2 ); \
+ fflush(stdout); \
+ } while ( 0 )
+
+
+#define sprint_time(_str, _s1, _tb, _s2) \
+ do { \
+ sprintf( (str), "%s%02d:%02d:%02d %02d/%02d/%04d%s", \
+ _s1, (_tb)->hour, (_tb)->minute, (_tb)->second, \
+ (_tb)->month, (_tb)->day, (_tb)->year, _s2 ); \
+ } while ( 0 )
+
+#define put_dot( _c ) \
+ do { \
+ putchar( _c ); \
+ FLUSH_OUTPUT(); \
+ } while ( 0 )
+
+#define new_line puts( "" )
+
+#define puts_nocr printf
+
+#ifdef RTEMS_TEST_NO_PAUSE
+#define rtems_test_pause() \
+ do { \
+ printf( "<pause>\n" ); \
+ FLUSH_OUTPUT(); \
+ } while ( 0 )
+
+#define rtems_test_pause_and_screen_number( _screen ) \
+ do { \
+ printf( "<pause - screen %d>\n", (_screen) ); \
+ FLUSH_OUTPUT(); \
+ } while ( 0 )
+#else
+#define rtems_test_pause() \
+ do { \
+ char buffer[ 80 ]; \
+ printf( "<pause>" ); \
+ FLUSH_OUTPUT(); \
+ gets( buffer ); \
+ puts( "" ); \
+ } while ( 0 )
+
+#define rtems_test_pause_and_screen_number( _screen ) \
+ do { \
+ char buffer[ 80 ]; \
+ printf( "<pause - screen %d>", (_screen) ); \
+ FLUSH_OUTPUT(); \
+ gets( buffer ); \
+ puts( "" ); \
+ } while ( 0 )
+#endif
+
+#define put_name( _name, _crlf ) \
+ do { char buf[6];int i=1;\
+ rtems_unsigned32 c0, c1, c2, c3; \
+ \
+ c0 = ((_name) >> 24) & 0xff; \
+ c1 = ((_name) >> 16) & 0xff; \
+ c2 = ((_name) >> 8) & 0xff; \
+ c3 = (_name) & 0xff; \
+ buf[0]=c0; \
+ if ( c1 ) {buf[i]=(char)c1; i++;} ; \
+ if ( c2 ) {buf[i]=(char)c2; i++;}; \
+ if ( c3 ) {buf[i]=(char)c3; i++;}; \
+ if ( (_crlf) ) {buf[i]='\n'; i++;}\
+ buf[i]=0;\
+ printf(buf);\
+ } while (0)
+
+#ifndef build_time
+#define build_time( TB, MON, DAY, YR, HR, MIN, SEC, TK ) \
+ { (TB)->year = YR; \
+ (TB)->month = MON; \
+ (TB)->day = DAY; \
+ (TB)->hour = HR; \
+ (TB)->minute = MIN; \
+ (TB)->second = SEC; \
+ (TB)->ticks = TK; }
+#endif
+
+#define task_number( tid ) \
+ ( rtems_get_index( tid ) - \
+ rtems_configuration_get_rtems_api_configuration()->number_of_initialization_tasks )
+
+static inline rtems_unsigned32 get_ticks_per_second( void )
+{
+ rtems_interval ticks_per_second;
+ (void) rtems_clock_get( RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second );
+ return ticks_per_second;
+}
+
+#define TICKS_PER_SECOND get_ticks_per_second()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+#include <bsp.h>
+#include <stdio.h>
+
+#include "appsupport.h"
+#include "rtems_process_wrapper.h"
+#include "traffic_shaping.h"
+
+unsigned int sink_processes;
+void sink_end_process(rtems_task_argument argument);
+void queue_status_process(rtems_task_argument argument);
+void shaping_process(rtems_task_argument argument);
+rtems_task shaping_init(rtems_task_argument argument) {
+ rtems_id task_id;
+ rtems_status_code status;
+ QUEUE_WRAPPER *queue_wrap, *sink_wrap;
+ rtems_name name;
+ int i;
+
+ // instatiate daemons for data transfer notices
+ queue_wrap = (QUEUE_WRAPPER *)malloc(NUMBER_OF_QUEUES *
+ sizeof(QUEUE_WRAPPER));
+ for (i=0; i < NUMBER_OF_QUEUES; i++) {
+ queue_wrap[i].q = scratch_queue_autoinit_shaper(i+1, 0, 0, 0);
+ queue_wrap[i].hasData = 0;
+ }
+
+ for (i=0; i< NUMBER_OF_QUEUES; i++) {
+ name = rtems_build_name('q', 's', i+1, 'c');
+ status = rtems_task_create(name,
+ 127,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_LOCAL,
+ &task_id, -1);
+ if (status != RTEMS_SUCCESSFUL) {
+ printf("[init ] Create queue process failed (status %d).\n",
+ status);
+ rtems_shutdown_executive(0);
+ }
+ status = rtems_task_start(task_id, queue_status_process,
+ (rtems_task_argument)&queue_wrap[i]);
+ if (status != RTEMS_SUCCESSFUL) {
+ printf("[init ] Start queue process failed (status %d).\n",
+ status);
+ rtems_shutdown_executive(0);
+ }
+ }
+
+ // instatiate daemons to wait for sinks finishing
+ sink_processes = NUMBER_OF_SINKS;
+ sink_wrap = (QUEUE_WRAPPER *)malloc(NUMBER_OF_SINKS *
+ sizeof(QUEUE_WRAPPER));
+ for (i=0; i<NUMBER_OF_SINKS; i++) {
+ sink_wrap[i].sem_terminate = get_sem_terminate(i+1);
+ }
+ for (i=0; i<NUMBER_OF_SINKS; i++) {
+ name = rtems_build_name('s', 't', i+1, 'c');
+ status = rtems_task_create(name,
+ 127,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_LOCAL,
+ &task_id, -1);
+ if (status != RTEMS_SUCCESSFUL) {
+ printf("[init ] Create sink process failed (status %d).\n",
+ status);
+ rtems_shutdown_executive(0);
+ }
+ status = rtems_task_start(task_id, sink_end_process,
+ (rtems_task_argument)&sink_wrap[i]);
+ if (status != RTEMS_SUCCESSFUL) {
+ printf("[init ] Start sink process failed (status %d).\n",
+ status);
+ rtems_shutdown_executive(0);
+ }
+ }
+
+
+ // intatiate daemon for data transfer
+ name = rtems_build_name('t', 's', NUMBER_OF_QUEUES, 'c');
+ status = rtems_task_create(name,
+ 128,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_LOCAL,
+ &task_id, -1);
+ if (status != RTEMS_SUCCESSFUL) {
+ printf("[init ] Create shaping process failed (status %d).\n",
+ status);
+ rtems_shutdown_executive(0);
+ }
+ status = rtems_task_start(task_id, shaping_process,
+ (rtems_task_argument)queue_wrap);
+ if (status != RTEMS_SUCCESSFUL) {
+ printf("[init ] Start shaping process failed (status %d).\n",
+ status);
+ rtems_shutdown_executive(0);
+ }
+
+ rtems_task_delete(RTEMS_SELF);
+}
+
+
+void queue_status_process(rtems_task_argument argument)
+{
+ QUEUE_WRAPPER *wrap = (QUEUE_WRAPPER *) argument;
+ SCRATCH_QUEUE_SHAPER *queue = wrap->q;
+
+/* printf("queue:%x, traffice_shaping: "
+ "\n\t sem_shaper_used:%x, "
+ "\n\t sem_shaper_left:%x, "
+ "\n\t semaphore_left:%x, "
+ "\n\t semaphore_used:%x",
+ wrap->q,
+ queue->sem_shaper_used,
+ queue->sem_shaper_left,
+ queue->semaphore_left,
+ queue->semaphore_used
+ ); */
+
+ while (1) {
+ // always USEINTERRUPT
+ ss_sem_wait(queue->sem_shaper_used);
+ ss_sem_wait(queue->sem_shaper_left);
+
+ wrap->hasData ++;
+ }
+}
+
+void sink_end_process(rtems_task_argument argument)
+{
+ QUEUE_WRAPPER *queue_wrap = (QUEUE_WRAPPER *) argument;
+
+ // wait for terminating signal from sink
+ ss_sem_wait(queue_wrap->sem_terminate);
+
+ sink_processes--;
+ if (sink_processes == 0) {
+ SHOW_DEBUG("END!!!");
+ exit(0);
+ }
+}
+
+static int cur_queue; // current queue
+QUEUE_WRAPPER * get_next_queue(QUEUE_WRAPPER * queue_wrap);
+int canSend(QUEUE_WRAPPER * queue);
+void shaping_process(rtems_task_argument argument)
+{
+ QUEUE_WRAPPER *queue_wrap = (QUEUE_WRAPPER *) argument;
+ cur_queue = 0;
+
+ while (1) {
+ QUEUE_WRAPPER *q_w;
+ q_w = get_next_queue(queue_wrap);
+
+ if (canSend(q_w)) {
+ if (q_w->hasData) {
+ scratch_queue_shaperRW(q_w->q);
+ q_w->hasData--;
+ }
+ }
+ }
+
+}
+
+#define PULL_MODE
+// queue scheduling
+QUEUE_WRAPPER * get_next_queue(QUEUE_WRAPPER * queue_wrap)
+{
+ // round robin
+#ifdef PULL_MODE
+ cur_queue = (cur_queue == 0) ? NUMBER_OF_QUEUES : cur_queue;
+ cur_queue --;
+#else // PUSH MODE
+ cur_queue++;
+ cur_queue = (cur_queue == NUMBER_OF_QUEUES) ? 0 : cur_queue;
+#endif
+ return &queue_wrap[cur_queue];
+}
+
+
+// shaping
+int canSend(QUEUE_WRAPPER * queue)
+{
+ return 1;
+}
+
+
+
--- /dev/null
+#ifndef TRAFFIC_SHAPING_H
+#define TRAFFIC_SHAPING_H
+
+#include "scratch_queue.h"
+
+typedef struct _queue_wrapper {
+ SCRATCH_QUEUE_SHAPER *q;
+ int hasData;
+ QUEUE_SEMAPHORE sem_terminate;
+} QUEUE_WRAPPER;
+
+#define @NUMBER_OF_QUEUES@ // generated
+#define @NUMBER_OF_SINKS@ // generated
+
+rtems_task shaping_init(rtems_task_argument argument);
+
+#endif
--- /dev/null
+/* $Id: MakefileVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.systemC;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a SystemC package Makefile.
+ */
+public class MakefileVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of the Makefile
+ */
+ public MakefileVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ * Create a Makefile for the given process network.
+ *
+ * @param x process network that needs to be rendered.
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+
+ ps.println("CXX = g++");
+ ps.println("CC = g++");
+ ps.println();
+ ps.println("SYSTEMC_INC = -I" + _ui.getSystemCINC());
+ ps.println("SYSTEMC_LIB = " + _ui.getSystemCLIB());
+ ps.println("MY_LIB_INC = -Ilib -Isc_wrappers -Iprocesses");
+ ps.println("VPATH = lib:sc_wrappers:processes");
+ ps.println();
+ ps.println("CXXFLAGS = -g -O0 -D__DOL_ETHZ_GEN__ $(SYSTEMC_INC) $(MY_LIB_INC)");
+ ps.println("CFLAGS = $(CXXFLAGS)");
+ ps.println();
+
+ ps.print("PROCESS_OBJS = dol.o ");
+ for (String basename : x.getProcessBasenames()) {
+ ps.print(basename + "_wrapper.o ");
+ }
+ ps.println();
+ ps.println();
+ ps.println("all:" + _name);
+ ps.println();
+ ps.println(_name + ": " + _name + ".o $(PROCESS_OBJS)");
+ ps.println("\t$(CXX) $(CXXFLAGS) -o $@ $^ $(SYSTEMC_LIB)");
+ ps.println("clean:");
+ ps.println("\t-rm -f *.o core core.* *.core " + _name);
+
+ } catch (Exception e) {
+ System.out.println(" SystemC Makefile Visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ protected String _dir = null;
+ protected String _name = "sc_application";
+}
--- /dev/null
+/* $Id: PNSystemCVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.systemC;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.util.Copier;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a SystemC package.
+ */
+public class PNSystemCVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param packageName Name of the SystemC directory
+ */
+ public PNSystemCVisitor(String packageName) {
+ _packageName = packageName;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered.
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ //_packageName = x.getName() + "SystemCPackage";
+ _generateDirHierarchy();
+
+ x.accept(new MakefileVisitor(_srcDir));
+ x.accept(new SCModuleVisitor(_srcDir));
+ x.accept(new ProcessVisitor(_wrapperDir));
+
+ }
+ catch (Exception e) {
+ System.out.println(" SystemC PN Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _generateDirHierarchy()
+ throws IOException, FileNotFoundException {
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ _srcDir = _packageName + _delimiter + _srcDirName;
+ dir = new File(_srcDir);
+ dir.mkdirs();
+
+ _libDir = _srcDir + _delimiter + _libDirName;
+ dir = new File(_libDir);
+ dir.mkdirs();
+
+ _processDir = _srcDir + _delimiter + _processDirName;
+ dir = new File(_processDir);
+ dir.mkdirs();
+
+ _wrapperDir = _srcDir + _delimiter + _wrapperDirName;
+ dir = new File(_wrapperDir);
+ dir.mkdirs();
+
+ //copy library files
+ File source = new File(_ui.getMySystemCLib());
+ File destination = new File(_libDir);
+ new Copier().copy(source, destination);
+
+ //copy process source code
+ source = new File(_srcDirName);
+ destination = new File(_processDir);
+ new Copier().copy(source, destination);
+ }
+
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+
+ protected String _libDir = "";
+ protected static String _libDirName = "lib";
+
+ protected String _processDir = "";
+ protected static String _processDirName = "processes";
+
+ protected String _wrapperDir = "";
+ protected static String _wrapperDirName = "sc_wrappers";
+
+ protected String _threadPostfix = "_thread";
+
+ protected CodePrintStream _mainPS = null;
+}
--- /dev/null
+/* $Id: ProcessVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.systemC;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.SourceCode;
+import dol.util.CodePrintStream;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * a SystemC wrapper for a process: process_wrapper.[h/cpp].
+ */
+public class ProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir target directory
+ */
+ public ProcessVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ Vector<String> pList = new Vector<String>();
+
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ pList.add(basename);
+ p.accept(this);
+ }
+ }
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param p process that needs to be rendered
+ */
+ public void visitComponent(Process p) {
+ try {
+ _createCppFile(p);
+ _createHeaderFile(p);
+ _adaptSources(p);
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _createCppFile(Process p) throws IOException {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ ps.printPrefixln("#include \"" + p.getBasename()
+ + "_wrapper.h\"");
+ ps.printPrefixln();
+
+ if (p.hasOutPorts()) {
+ //DOL_write()
+ ps.printPrefixln("static inline int DOL_write(void *port, "
+ + "void *buf, int len, DOLProcess *process)");
+ ps.printLeftBracket();
+ ps.printPrefixln("char *str = (char *)buf;");
+ ps.printPrefixln("while (len-- > 0) ");
+ ps.printLeftBracket();
+
+ int j = 0;
+ for (Port ip : p.getPortList()) {
+ if (ip.isOutPort()) {
+ String s = (j++ == 0) ? "if " : " else if ";
+ ps.printPrefixln(s + "(strstr(\" OUTPORT_"
+ + ip.getName() + "\", (const char*)port)) ");
+ ps.printLeftBracket();
+ ps.printPrefixln("(static_cast<" + p.getBasename()
+ + "_wrapper *>(process->wptr))->OUTPORT_"
+ + ip.getName() + "->write(*(str++));");
+ ps.printRightBracket();
+ }
+ }
+ ps.printRightBracket();
+ ps.printRightBracket();
+
+ //DOL_wtest()
+ ps.printPrefixln("static inline int DOL_wtest(void *port, "
+ + "int len, DOLProcess *process)");
+ ps.printLeftBracket();
+ j = 0;
+ for (Port ip : p.getPortList()) {
+ if (ip.isOutPort()) {
+ String s = (j++ == 0) ? "if " : "else if ";
+ ps.printPrefixln(s + "(strstr(\" OUTPORT_"
+ + ip.getName() + "\", (const char*)port)) ");
+ ps.printLeftBracket();
+ ps.printPrefixln("return (static_cast<" + p.getBasename()
+ + "_wrapper *>(process->wptr))->OUTPORT_"
+ + ip.getName() + "->wtest(len);");
+ ps.printRightBracket();
+ }
+ }
+ ps.printRightBracket();
+ }
+
+ ps.printPrefixln();
+ if (p.hasInPorts()) {
+ //DOL_read()
+ ps.printPrefixln("static inline int DOL_read(void *port, "
+ + "void *buf, int len, DOLProcess *process)");
+ ps.printLeftBracket();
+ ps.printPrefixln("char *str = (char *)buf;");
+ ps.printPrefixln("while (len-- > 0)");
+ ps.printLeftBracket();
+
+ int j = 0;
+ for (Port ip : p.getPortList()) {
+ if (ip.isInPort()) {
+ String s = (j++ == 0) ? "if " : "else if ";
+ ps.printPrefixln(s + "(strstr(\" INPORT_"
+ + ip.getName() + "\", (const char*)port))");
+ ps.printLeftBracket();
+ ps.printPrefixln("(static_cast<" + p.getBasename()
+ + "_wrapper *>(process->wptr))->INPORT_"
+ + ip.getName() + "->read(*(str++));");
+ ps.printRightBracket();
+ }
+ }
+ ps.printRightBracket();
+ ps.printRightBracket();
+
+ //DOL_rtest()
+ ps.printPrefixln("static inline int DOL_rtest(void *port, "
+ + "int len, DOLProcess *process)");
+ ps.printLeftBracket();
+ j = 0;
+ for (Port ip : p.getPortList()) {
+ if (ip.isInPort()) {
+ String s = (j++ == 0) ? "if " : " else if ";
+ ps.printPrefixln(s + "(strstr(\" INPORT_"
+ + ip.getName() + "\", (const char*)port))");
+ ps.printLeftBracket();
+ ps.printPrefixln("return (static_cast<" + p.getBasename()
+ + "_wrapper *>(process->wptr))->INPORT_"
+ + ip.getName() + "->rtest(len);");
+ ps.printRightBracket();
+ }
+ }
+ ps.printRightBracket();
+
+ }
+
+ ps.printPrefixln();
+ ps.printPrefixln("static inline int DOL_detach(DOLProcess *p)");
+ ps.printLeftBracket();
+ ps.printPrefixln("(static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))" + "->setDetached();");
+ ps.printRightBracket();
+ ps.printPrefixln();
+
+ ps.printPrefixln("#define GETINDEX(dimension) \\");
+ ps.printPrefixln("(static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))->_processIndex[dimension]");
+ ps.printPrefixln();
+
+ //include c file
+ for (SourceCode sr : p.getSrcList()) {
+ ps.printPrefixln("#include \"" + sr.getLocality() + "\"");
+ }
+ ps.printPrefixln();
+
+
+ ps.printPrefixln("void " + p.getBasename()
+ + "_wrapper::setDetached() { _detached = 1; }");
+ ps.printPrefixln("int " + p.getBasename()
+ + "_wrapper::isDetached() { return _detached; }");
+ ps.printPrefixln();
+
+ //constructor
+ ps.printPrefixln(p.getBasename() + "_wrapper::" + p.getBasename()
+ + "_wrapper(sc_module_name name=sc_gen_unique_name(\""
+ + p.getBasename() + "\" )) : sc_module(name), "
+ // + "_process(" + p.getBasename() + "), "
+ + "_detached(0)");
+ ps.printLeftBracket();
+ ps.printPrefixln("_state = (LocalState)new "
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State;");
+ //ps.printPrefixln("struct _local_states *_state = "
+ // + "new struct _local_states;");
+ //ps.printPrefixln("memcpy(_state, " + p.getBasename()
+ // + ".local, sizeof(struct _local_states));");
+ ps.printPrefixln("_process.local = _state;");
+ //ps.printPrefixln("sprintf(_process.local->id, name);");
+ ps.printPrefixln("_process.init = " + p.getBasename() + "_init;");
+ ps.printPrefixln("_process.fire = " + p.getBasename() + "_fire;");
+ ps.printPrefixln("_process.wptr = this;");
+ ps.printPrefixln();
+ ps.printPrefixln("char buffer[255];");
+ ps.printPrefixln("sprintf(buffer, name);");
+ ps.printPrefixln("for (int i = 0; i < 4; i++)");
+ ps.printPrefixln(" _processIndex[i] = "
+ + "getIndex(buffer, \"_\", i);");
+
+ ps.printPrefixln();
+ ps.printRightBracket();
+
+ ps.printPrefixln();
+ ps.printPrefixln("void " + p.getBasename()
+ + "_wrapper::initialize()");
+ ps.printLeftBracket();
+ ps.printPrefixln("_process.init(&_process);");
+ ps.printRightBracket();
+ ps.printPrefixln();
+ ps.printPrefixln("int " + p.getBasename() + "_wrapper::fire()");
+ ps.printLeftBracket();
+ ps.printPrefixln("return _process.fire(&_process);");
+ ps.printRightBracket();
+ ps.printPrefixln();
+ ps.printPrefixln(p.getBasename() + "_wrapper::~" + p.getBasename()
+ + "_wrapper()");
+ ps.printLeftBracket();
+ ps.printPrefixln("if (_state)");
+ ps.printLeftBracket();
+ ps.printPrefixln("delete ("
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State*)_state;");
+ ps.printRightBracket();
+ ps.printRightBracket();
+ }
+
+ protected void _createHeaderFile(Process p)
+ throws IOException {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.h";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ ps.printPrefixln("#ifndef " + p.getBasename() + "_WRAPPER_H");
+ ps.printPrefixln("#define " + p.getBasename() + "_WRAPPER_H");
+ ps.printPrefixln();
+ ps.printPrefixln("#include \"systemc.h\"");
+ ps.printPrefixln();
+ ps.printPrefixln("#include \"dol_sched_if.h\"");
+ ps.printPrefixln("#include \"dol_fifo_if.h\"");
+ ps.printPrefixln("#include \"simple_fifo.h\"");
+ ps.printPrefixln();
+ ps.printPrefixln("#include <dol.h>");
+ ps.printPrefixln();
+ ps.printPrefixln("class " + p.getBasename() +
+ "_wrapper : virtual public dol_sched_if, " +
+ "public sc_module");
+ ps.printLeftBracket();
+ ps.printPrefixln("public:");
+
+ for (Port pr : p.getPortList()) {
+ if (pr.isOutPort()) {
+ ps.printPrefixln("sc_port<write_if> OUTPORT_" +
+ pr.getName() + ";");
+ }
+ else if (pr.isInPort()) {
+ ps.printPrefixln("sc_port<read_if> INPORT_" +
+ pr.getName() + ";");
+ }
+ }
+ ps.printPrefixln("int _processIndex[4];");
+
+ ps.printPrefixln();
+ ps.printPrefixln("" + p.getBasename()
+ + "_wrapper(sc_module_name name);");
+ ps.printPrefixln();
+ ps.printPrefixln("virtual ~" + p.getBasename() + "_wrapper();");
+ ps.printPrefixln();
+ ps.printPrefixln("// DOL scheduler interface");
+ ps.printPrefixln("void initialize();");
+ ps.printPrefixln("int fire();");
+ ps.printPrefixln("void setDetached();");
+ ps.printPrefixln("int isDetached();");
+ ps.printPrefixln();
+ ps.printPrefixln();
+ ps.printPrefixln("protected:");
+ ps.printPrefixln("LocalState _state;");
+
+ ps.printPrefixln();
+ ps.printPrefixln("private:");
+ ps.printPrefixln("" + p.getBasename() + "_wrapper( const "
+ + p.getBasename() + "_wrapper& );");
+ ps.printPrefixln("" + p.getBasename() + "_wrapper& operator = "
+ + "( const " + p.getBasename() + "_wrapper& );");
+ ps.printPrefixln("DOLProcess _process;");
+ ps.printPrefixln("int _detached;");
+ ps.printRightBracket();
+ ps.printPrefixln(";");
+ ps.printPrefixln("#endif");
+ }
+
+ /**
+ * Make modifications to source files of a process.
+ * Port names need to be strings for the SystemC code generation.
+ * Therefore, in the header files integer port names are put into
+ * quotation marks.
+ *
+ * @param p process whose sources should be adapted
+ * @throws IOException
+ */
+ protected void _adaptSources(Process p) throws IOException {
+ Sed sed = new Sed();
+ for (Port port : p.getPortList()) {
+ String processHeaderFile;
+
+ for (SourceCode sr : p.getSrcList()) {
+ processHeaderFile = _dir + _delimiter + ".."
+ + _delimiter + "processes" + _delimiter
+ + sr.getLocality().
+ replaceAll("(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ sed.sed(processHeaderFile,
+ "(#define[ ]*PORT_\\w*[ ]*)\"?"
+ + port.getBasename() + "\"?[ ]*$",
+ "$1 " + "\"" + port.getBasename() + "\"");
+ }
+ }
+ }
+
+
+ protected String _dir = null;
+}
--- /dev/null
+/* $Id: SCModuleVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.systemC;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * the top sc module: sc_applicaion.cpp.
+ */
+public class SCModuleVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param dir path of this file
+ */
+ public SCModuleVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ String filename = _dir + _delimiter + "sc_application.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ _mainPS = new CodePrintStream(file);
+
+ _mainPS.printPrefixln("#include <systemc>");
+ _mainPS.printPrefixln("#include <list>");
+ _mainPS.printPrefixln("#include \"dol_fifo.h\"");
+ _mainPS.printPrefixln("#include \"dol_sched_if.h\"");
+ _mainPS.println();
+
+ for (String basename : x.getProcessBasenames()) {
+ _mainPS.printPrefixln("#include \"" + basename
+ + "_wrapper.h\"");
+ }
+ _mainPS.println();
+ _mainPS.printPrefixln("using namespace std;");
+
+ _mainPS.println();
+ _mainPS.printPrefixln("class sc_application : public sc_module ");
+ _mainPS.printLeftBracket();
+
+ _mainPS.printPrefixln("public:");
+ _mainPS.printPrefixln("SC_HAS_PROCESS(sc_application);");
+
+ //declare processes
+ _mainPS.println();
+ for (Process p : x.getProcessList()) {
+ _mainPS.printPrefixln(p.getBasename() + "_wrapper "
+ + p.getName() + "_ins"+ ";");
+ _mainPS.printPrefixln("sc_event " + p.getName()
+ + "_event;");
+ }
+ _mainPS.println();
+
+ //define the scheduler
+ _mainPS.printPrefixln("sc_event sched_event;");
+ _mainPS.printPrefixln("list<sc_event* > eventList;");
+ _mainPS.printPrefixln("list<sc_event* >::iterator iter;");
+ _mainPS.println();
+
+ //declare channels
+ _mainPS.println();
+ for (Channel p : x.getChannelList()) {
+ _mainPS.printPrefixln("fifo " + p.getName() + "_ins;");
+ }
+ _mainPS.println();
+
+ //model constructor
+ _mainPS.printPrefixln("sc_application(sc_module_name name)");
+
+ //parameter of constructor
+ _mainPS.printPrefix(": sc_module(name)");
+ for (Process p : x.getProcessList()) {
+ _mainPS.println(",");
+ _mainPS.printPrefix(p.getName() + "_ins(\""
+ + p.getName() +"\")");
+ }
+
+ if (x.getChannelList().size() > 0) {
+ for (Channel c : x.getChannelList()) {
+ _mainPS.println(",");
+ _mainPS.printPrefix(c.getName() + "_ins("
+ + "\"" + c.getName() + "\", "
+ + c.getSize() * c.getTokenSize()
+ + ")");
+ }
+ }
+ _mainPS.println("");
+ _mainPS.printLeftBracket();
+
+ //construtor content
+ //build the network
+ for (Channel p : x.getChannelList()) {
+ p.accept(this);
+ }
+ _mainPS.println("");
+
+ _mainPS.println("");
+
+ _mainPS.printPrefixln("SC_THREAD(thread_init);");
+ //init thread
+ _mainPS.printPrefixln("SC_THREAD(thread_sched);");
+
+ //declare concurrent non-terminating threads
+ for (Process p : x.getProcessList()) {
+ _mainPS.printPrefixln("SC_THREAD(thread_" +
+ p.getName() + ");");
+ }
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+ //define scheduler thread
+ _mainPS.printPrefixln("void thread_init()");
+ _mainPS.printLeftBracket();
+ //init
+ for (Process p : x.getProcessList()) {
+ _mainPS.printPrefixln(p.getName() + "_ins.initialize();");
+ }
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+
+ //different scheduling algorithm can be put here
+ _mainPS.printPrefixln("void thread_sched()");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("while (1)");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("for (iter=eventList.begin(); iter != "
+ + "eventList.end(); ++iter)");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("sc_event* e = (*iter);");
+ _mainPS.printPrefixln("notify(*e);");
+ _mainPS.printRightBracket();
+ _mainPS.printPrefixln("eventList.clear();");
+ _mainPS.printPrefixln("wait(sched_event);");
+ _mainPS.printRightBracket();
+ _mainPS.printRightBracket();
+ _mainPS.println();
+
+ //define threads
+ for (Process p : x.getProcessList()) {
+ p.accept(this);
+ }
+
+ _mainPS.printRightBracket(); // end of class
+ _mainPS.println(";");
+
+ //create and run the simulator
+ _mainPS.printPrefixln("int sc_main (int argc, char *argv[])");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("sc_report_handler::set_actions(\""
+ + "/IEEE_Std_1666/deprecated\", SC_DO_NOTHING);");
+ _mainPS.printPrefixln("sc_report::register_id("
+ + "RP_ID_PARAMETER_PROBLEM, "
+ + "\"parameter problem\" );");
+
+ //create an instance of the application model
+ //remove potential whitespaces before using the process
+ //network name as a systemc identifier
+ _mainPS.printPrefixln("sc_application my_app_mdl(\""
+ + x.getName().replaceAll(" ", "") + "\");");
+ _mainPS.printPrefixln("sc_start(-1,SC_NS);");
+ _mainPS.printPrefixln("return 0;");
+
+ _mainPS.printRightBracket();
+
+ }
+ catch (Exception e) {
+ System.out.println(" SystemC module visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Print a line for the process in the correct format for DOTTY.
+ *
+ * @param x process that needs to be rendered
+ */
+ public void visitComponent(Process x) {
+ _mainPS.printPrefixln("void thread_" + x.getName() + "()");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln("while (!" + x.getName()
+ + "_ins.isDetached())");
+ _mainPS.printLeftBracket();
+ _mainPS.printPrefixln(x.getName() + "_ins.fire();");
+ _mainPS.printPrefixln("eventList.push_back(&" + x.getName()
+ + "_event);");
+ _mainPS.printPrefixln("sched_event.notify();");
+ _mainPS.printPrefixln("wait(" + x.getName() + "_event);");
+
+ _mainPS.printRightBracket();
+ _mainPS.printRightBracket();
+ }
+
+ /**
+ *
+ * @param x channel that needs to be rendered
+ */
+ public void visitComponent(Channel x) {
+ for (Port p : x.getPortList()) {
+ if (p.isOutPort()) {
+ //we get port name from channel
+ //channel.out == process.in
+ _mainPS.printPrefixln(p.getPeerResource().getName()
+ + "_ins.INPORT_" + p.getPeerPort().getName()
+ + "(" + x.getName() + "_ins);");
+ } else if (p.isInPort()) {
+ _mainPS.printPrefixln(p.getPeerResource().getName()
+ + "_ins.OUTPORT_" + p.getPeerPort().getName()
+ + "(" + x.getName() + "_ins);");
+ }
+ }
+ }
+
+ protected CodePrintStream _mainPS = null;
+ protected String _dir = null;
+}
--- /dev/null
+#include "dol.h"\r
+\r
+/**\r
+ * Create the port name of an iterated port based on its basename and the\r
+ * given indices.\r
+ * Example: createPort(xxx, "port", 2, 1, N1, 3, N2) will result in xxx\r
+ * having the value "port_1_3". The range definitions N1, N2 will be ignored\r
+ * in this implementation\r
+ *\r
+ * @param port buffer where the result is stored\r
+ * @param base basename of the port\r
+ * @param number_of_indices number of dimensions of the port\r
+ * @param index_range_pairs index and range values for each dimension\r
+ */\r
+char* createPort(char* port, char* base,\r
+ int number_of_indices, int indices, ...) {\r
+ char next_index_string[10];\r
+ strcpy(port, base);\r
+\r
+ if (number_of_indices > 4) {\r
+ printf("Error: iterated ports must not have more than ");\r
+ printf("4 dimensions.\n");\r
+ exit(-1);\r
+ }\r
+\r
+ va_list argumentlist;\r
+ va_start(argumentlist, indices);\r
+\r
+ if (number_of_indices > 0) {\r
+ sprintf(next_index_string, "_%d", indices);\r
+ strcat(port, next_index_string);\r
+\r
+ for (int k = 1; k < number_of_indices; k++) {\r
+ va_arg(argumentlist, int); //skip the range value\r
+ sprintf(next_index_string, "_%d", va_arg(argumentlist, int));\r
+ strcat(port, next_index_string);\r
+ }\r
+ }\r
+ return port;\r
+}\r
+\r
+/**\r
+ * Gets an index of a string, where the index must be separated by\r
+ * a character specified in tokens.\r
+ * Returns -1, when an error occurs.\r
+ *\r
+ * Example:\r
+ * getIndex("name_1_2", "_", 0) will return 1.\r
+ * getIndex("name_1_2", "_", 1) will return 2.\r
+ *\r
+ * @param string string to parse\r
+ * @param tokens delimiter of indices\r
+ * @param indexNumber position of index (starting at 0)\r
+ */\r
+int getIndex(const char* string, char* tokens, int indexNumber) {\r
+ char* string_copy;\r
+ char* token_pointer;\r
+ int index = 0;\r
+\r
+ string_copy = (char*) malloc(sizeof(char) * (strlen(string) + 1));\r
+ if (!string_copy) {\r
+ fprintf(stderr, "getIndex(): could not allocate memory.\n");\r
+ return -1;\r
+ }\r
+\r
+ strcpy(string_copy, string);\r
+\r
+ token_pointer = strtok(string_copy, tokens);\r
+ do {\r
+ token_pointer = strtok(NULL, tokens);\r
+ index++;\r
+ } while (index <= indexNumber && token_pointer != 0);\r
+\r
+ if (token_pointer) {\r
+ index = atoi(token_pointer);\r
+ free(string_copy);\r
+ return index;\r
+ }\r
+\r
+ return -1;\r
+}\r
--- /dev/null
+#ifndef DOL_H
+#define DOL_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/************************************************************************
+ * do not add code to this header
+ ************************************************************************/
+
+/**
+ * - Local variables for each process can be defined in the structure
+ * LocalState. For each process, a new instance of LocalState is
+ * instantiated.
+ * - The ProcessInit function pointer points to the function which is
+ * called to initialize a process.
+ * - The ProcessFire function pointer points to the function which is
+ * called repeatedly by the scheduler.
+ * - The wptr is a placeholder for callback. A pointer to the wrapper
+ * class instance of the process can be assigned. This is done in the
+ * code generated by the code generation, so one can just leave it
+ * blank.
+ */
+
+//structure for local memory of process
+typedef struct _local_states *LocalState;
+
+//additional behavioral functions could be declared here
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+//process handler
+struct _process;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr; //placeholder for wrapper instance
+} DOLProcess;
+
+
+//macros to deal with iterated ports
+
+/**
+ * macro to create a variable to store a port name
+ *
+ * @param name name of the variable
+ */
+#define MAX_PORT_NAME_LENGTH 255
+#define CREATEPORTVAR(name) char name[MAX_PORT_NAME_LENGTH]
+
+
+/**
+ * Create the port name of an iterated port based on its basename and the
+ * given indices.
+ *
+ * @param port buffer where the result is stored (created using
+ * CREATEPORTVAR)
+ * @param base basename of the port
+ * @param number_of_indices number of dimensions of the port
+ * @param index_range_pairs index and range values for each dimension
+ */
+#define CREATEPORT(port, base, number_of_indices, indices...) \
+ createPort(port, base, number_of_indices, indices)
+
+char* createPort(char* port,
+ char* base,
+ int number_of_indices,
+ int indices, ...);
+
+int getIndex(const char* string, char* tokens, int indexNumber);
+
+#endif
--- /dev/null
+/**************************************************************************
+ dol_fifo.h
+
+ DOL FIFO channel:
+ relative bloking (RB) and relative non-bloking (RN)
+ task transaction level (TTL) fifo channel
+
+ (c) 2006 by Alexander Maxiaguine <maxiagui@tik.ee.ethz.ch>
+
+ Computer Engineering and Networks Laboratory, TIK
+ Swiss Federal Institute of Technology, ETHZ Zurich
+ Switzerland
+
+**************************************************************************/
+
+/**************************************************************************
+ Change Log:
+
+ 14.03.06 -- creation
+
+**************************************************************************/
+
+#ifndef DOL_FIFO_H
+#define DOL_FIFO_H
+
+#include <typeinfo>
+#include "systemc.h"
+
+#include "dol_rp_ids.h"
+#include "dol_fifo_if.h"
+
+
+template <class T>
+class dol_fifo
+: public dol_fifo_write_if<T>,
+ public dol_fifo_read_if<T>,
+ public sc_prim_channel
+{
+public:
+
+ // constructors
+ explicit dol_fifo( int size ) : sc_prim_channel( sc_gen_unique_name( "dol_fifo" ) )
+ { init( size ); }
+
+ explicit dol_fifo( const char* name, int size) : sc_prim_channel( name)
+ { init( size ); }
+
+ // destructor
+ virtual ~dol_fifo()
+ { delete [] m_buf; }
+
+ virtual void register_port( sc_port_base&, const char* );
+
+ // ********* WRITE interface methods **************
+ // bloking (re)acquire free room in the channel
+ virtual void reAcquireRoom(int count);
+
+ // non-bloking (re)acquire free room in the channel
+ virtual bool tryReAcquireRoom(int count);
+
+ // store data into the acquired free room
+ virtual void store(int offset, T* data, int count);
+
+ // release the stored data to the channel (commit write)
+ virtual void releaseData(int count);
+
+ // ********* READ interface methods **************
+ // bloking (re)acquire data in the channel
+ virtual void reAcquireData(int count);
+
+ // non-bloking (re)acquire data in the channel
+ virtual bool tryReAcquireData(int count);
+
+ // load the acquired data into a vector
+ virtual void load(int offset, T* vector, int count);
+
+ // free up the room in the channel (commit read)
+ virtual void releaseRoom(int count);
+
+
+ // ***************************************
+ // helper methods (for debug, etc.)
+
+ bool in_deadlock() {
+ return reader_is_blocked && writer_is_blocked;
+ }
+
+ void trace( sc_trace_file* tf ) const;
+ virtual void print( ::std::ostream& = ::std::cout ) const;
+ virtual void dump( ::std::ostream& = ::std::cout ) const;
+
+
+ virtual const char* kind() const
+ { return "dol_fifo"; }
+
+
+protected:
+
+ virtual void update();
+ void init( int );
+
+
+protected:
+
+ int m_size; // buffer size
+ T* m_buf; // the buffer
+
+ // channel state variables
+ int m_rwin_head; // index of read window head (oldest full token)
+ int m_wwin_head; // index of write window head (oldest empty token)
+
+ int m_readable; // number of readable tokens (number of full tokens)
+ int m_acquired_room; // size of acquired room (write window)
+ int m_acquired_data; // size of acquired data (read window)
+
+ int m_released_data; // size of data (filled tokens) released during this delta cycle
+ int m_released_room; // size of room (emptied tokens) released during this delta cycle
+
+
+ // SC specific properties
+ sc_event m_data_released_event;
+ sc_event m_room_released_event;
+
+ sc_port_base* m_reader; // used for static design rule checking
+ sc_port_base* m_writer; // used for static design rule checking
+
+ // used to detect deadlocks
+ bool reader_is_blocked;
+ bool writer_is_blocked;
+
+private:
+
+ // disabled
+ dol_fifo( const dol_fifo<T>& );
+ dol_fifo& operator = ( const dol_fifo<T>& );
+};
+
+
+
+
+// ************ Implementation ************************************
+
+// *** WRITE interface methods ****
+
+// blocking (re)acquire free room of size COUNT in the channel
+template <class T>
+inline void dol_fifo<T>::reAcquireRoom( int count )
+{
+ while( m_size - m_readable < count ) {
+ if( m_size < count) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Requested room is larger than total available buffer space \n --> This is a deadlock\n\n");
+ }
+
+ writer_is_blocked = true;
+ sc_core::wait( m_room_released_event );
+ writer_is_blocked = false;
+ }
+ m_acquired_room = count;
+}
+
+// non-bloking (re)acquire free room in the channel
+template <class T>
+inline bool dol_fifo<T>::tryReAcquireRoom( int count )
+{
+ if( m_size - m_readable < count ) {
+ if( m_size < count) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Requested room is larger than the total available buffer space \n\n");
+ }
+ return false;
+ }
+ m_acquired_room = count;
+ return true;
+}
+
+// write COUNT data into the acquired free room starting from the position indicated by OFFSET
+template <class T>
+inline void dol_fifo<T>::store( int offset, T* data, int count )
+{
+ // sanity checks
+ if( m_acquired_room <= 0) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to write without acquiring the room\n --> I ignore this action\n\n");
+ return;
+ }
+ if( offset > m_acquired_room - 1 ) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to write beyond the acquired room: offset value may be too large\n --> I ignore this action\n\n");
+ return;
+ }
+ if( count > m_acquired_room - offset ) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to write beyound the acquired room: data size may be too large\n --> I'm decreasing the data size\n\n");
+ count = m_acquired_room - offset;
+ }
+
+ int wi = ( m_wwin_head + offset ) % m_size;
+ for(int i=0; i<count; i++ ) {
+ m_buf[wi] = data[i];
+ wi = ( wi + 1 ) % m_size;
+ }
+}
+
+// release COUNT stored data to the channel (commit write)
+template <class T>
+inline void dol_fifo<T>::releaseData( int count )
+{
+ // sanity check
+ if( count > m_acquired_room ) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to release more room than was acquired\n --> I'm decreasing the size of released room\n\n");
+ count = m_acquired_room;
+ }
+
+ m_readable += count;
+ m_released_data += count;
+
+ m_acquired_room -= count;
+ m_wwin_head = ( m_wwin_head + count ) % m_size;
+
+ request_update();
+}
+
+
+// *** READ interface methods ****
+
+// bloking (re)acquire COUNT data in the channel
+template <class T>
+inline void dol_fifo<T>::reAcquireData( int count )
+{
+ while( m_readable < count ) {
+ if( m_size < count) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Acquired data size is larger than total available buffer space\n --> This is a deadlock\n\n");
+ }
+
+ reader_is_blocked = true;
+ sc_core::wait( m_data_released_event );
+ reader_is_blocked = false;
+ }
+
+ m_acquired_data = count;
+}
+
+// non-bloking (re)acquire COUNT data in the channel
+template <class T>
+inline
+bool
+dol_fifo<T>::tryReAcquireData( int count ) {
+ if( m_readable < count ) {
+
+ if( m_size < count) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Acquired data size is larger than total available buffer space \n\n");
+ }
+ return false;
+ }
+
+ m_acquired_data = count;
+ return true;
+}
+
+// load COUNT acquired data into a vector
+// from the read window starting at the position indicated by OFFSET
+template <class T>
+inline void dol_fifo<T>::load( int offset, T* vector, int count )
+{
+ // sanity checks
+ if( m_acquired_data <= 0) {
+
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to load without acquiring the data\n --> I ignore this action\n\n");
+ return;
+ }
+
+ if( offset > m_acquired_data - 1 ) {
+
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to read beyond the acquired data: offset value may be too large\n --> I ignore this action\n\n");
+ return;
+ }
+
+ if( count > m_acquired_data - offset ) {
+
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to read beyound the acquired data: data size may be too large\n --> I'm decreasing the data size\n\n");
+ count = m_acquired_data - offset;
+ }
+
+
+ int ri = ( m_rwin_head + offset ) % m_size;
+
+ for(int i=0; i<count; i++ ) {
+ vector[i] = m_buf[ri];
+ ri = ( ri + 1 ) % m_size;
+ }
+}
+
+// free up COUNT room in the channel (commit read)
+template <class T>
+inline void dol_fifo<T>::releaseRoom( int count )
+{
+ // sanity check
+ if( count > m_acquired_data ) {
+ SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to free up more room than was acquired\n --> I'm decreasing the size of released room\n\n");
+ count = m_acquired_data;
+ }
+
+ m_readable -= count;
+ m_released_room += count;
+
+ m_acquired_data -= count;
+ m_rwin_head = ( m_rwin_head + count ) % m_size;
+
+ request_update();
+}
+
+
+
+
+// *** Other methods ***
+
+
+template <class T>
+inline void dol_fifo<T>::update()
+{
+ if( m_released_room > 0 ) {
+ m_room_released_event.notify_delayed();
+ }
+
+ if( m_released_data > 0 ) {
+ m_data_released_event.notify_delayed();
+ }
+
+ m_released_room = 0;
+ m_released_data = 0;
+}
+
+
+template <class T>
+inline void dol_fifo<T>::init( int size )
+{
+ if( size <= 0 ) {
+ SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 );
+ }
+
+ m_size = size;
+ m_buf = new T[m_size];
+
+ m_readable = 0;
+
+ m_acquired_room = 0;
+ m_acquired_data = 0;
+
+ m_rwin_head = 0;
+ m_wwin_head = 0;
+
+ m_released_data = 0;
+ m_released_room = 0;
+
+ m_reader = 0;
+ m_writer = 0;
+
+ reader_is_blocked = false;
+ writer_is_blocked = false;
+}
+
+
+template <class T>
+inline void dol_fifo<T>::register_port( sc_port_base& port_,
+ const char* if_typename_ )
+{
+ std::string nm( if_typename_ );
+ if( nm == typeid( dol_fifo_read_if<T> ).name() ) {
+ // only one reader can be connected
+ if( m_reader != 0 ) {
+ SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 );
+ }
+ m_reader = &port_;
+ } else { // nm == typeid( dol_fifo_write_if<T> ).name()
+ // only one writer can be connected
+ if( m_writer != 0 ) {
+ SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 );
+ }
+ m_writer = &port_;
+ }
+}
+
+
+
+template <class T>
+inline void dol_fifo<T>::trace( sc_trace_file* tf ) const
+{
+#ifdef DEBUG_SYSTEMC
+ char buf[32];
+ std::string nm = name();
+ for( int i = 0; i < m_size; ++ i ) {
+ sprintf( buf, "_%d", i );
+ sc_trace( tf, m_buf[i], nm + buf );
+ }
+#endif
+}
+
+
+template <class T>
+inline void dol_fifo<T>::print( ::std::ostream& os ) const
+{
+ if( m_readable ) {
+ for(int j=0, i = m_rwin_head; j<m_readable; j++) {
+// os << m_buf[i] << ::std::endl;
+ os << m_buf[i];
+ i = ( i + 1 ) % m_size;
+ }
+ }
+ os << ::std::endl;
+}
+
+template <class T>
+inline void dol_fifo<T>::dump( ::std::ostream& os ) const
+{
+ os << "name = " << name() << ::std::endl;
+ if( m_readable ) {
+ for(int j=0, i = m_rwin_head; j<m_readable; j++) {
+ os << "value[" << j << "] = " << m_buf[i] << ::std::endl;
+ i = ( i + 1 ) % m_size;
+
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+
+template <class T>
+inline ::std::ostream& operator << ( ::std::ostream& os, const dol_fifo<T>& a )
+{
+ a.print( os );
+ return os;
+}
+
+
+#endif
--- /dev/null
+/**************************************************************************\r
+ dol_fifo_if.h\r
+ \r
+ DOL FIFO channel interfaces \r
+\r
+ (c) 2006 by Alexander Maxiaguine <maxiagui@tik.ee.ethz.ch>\r
+\r
+ Computer Engineering and Networks Laboratory, TIK\r
+ Swiss Federal Institute of Technology, ETHZ Zurich \r
+ Switzerland\r
+\r
+**************************************************************************/\r
+\r
+/**************************************************************************\r
+ Change Log:\r
+\r
+ 14.03.06 -- creation\r
+\r
+**************************************************************************/\r
+\r
+#ifndef DOL_FIFO_IF_H\r
+#define DOL_FIFO_IF_H\r
+\r
+#include "systemc.h"\r
+\r
+\r
+template <class T>\r
+class dol_fifo_write_if : virtual public sc_interface\r
+{\r
+public:\r
+ \r
+ // bloking (re)acquire free room in the channel\r
+ virtual void reAcquireRoom(int count) = 0;\r
+ \r
+ // non-bloking (re)acquire free room in the channel\r
+ virtual bool tryReAcquireRoom(int count) = 0;\r
+ \r
+ // store data into the acquired free room\r
+ virtual void store(int offset, T* data, int count) = 0;\r
+ \r
+ // release the stored data to the channel (commit write)\r
+ virtual void releaseData(int count) = 0;\r
+\r
+ \r
+protected:\r
+ \r
+ // constructor\r
+ dol_fifo_write_if() {}\r
+\r
+ \r
+private:\r
+\r
+ // disabled\r
+ dol_fifo_write_if( const dol_fifo_write_if<T>& );\r
+ dol_fifo_write_if<T>& operator = ( const dol_fifo_write_if<T>& );\r
+};\r
+\r
+template <class T>\r
+class dol_fifo_read_if : virtual public sc_interface\r
+{\r
+public:\r
+\r
+ // bloking (re)acquire data in the channel\r
+ virtual void reAcquireData(int count) = 0;\r
+\r
+ // non-bloking (re)acquire data in the channel\r
+ virtual bool tryReAcquireData(int count) = 0;\r
+ \r
+ // load the acquired data into a vector\r
+ virtual void load(int offset, T* vector, int count) = 0;\r
+ \r
+ // free up the room in the channel (commit read)\r
+ virtual void releaseRoom(int count) = 0;\r
+ \r
+ \r
+protected:\r
+ \r
+ // constructor\r
+ dol_fifo_read_if() {}\r
+\r
+ \r
+private:\r
+\r
+ // disabled\r
+ dol_fifo_read_if( const dol_fifo_read_if<T>& );\r
+ dol_fifo_read_if<T>& operator = ( const dol_fifo_read_if<T>& );\r
+};\r
+\r
+\r
+#endif\r
--- /dev/null
+/**************************************************************************\r
+ dol_rp_ids.h\r
+ \r
+ Report IDs\r
+\r
+ (c) 2006 by Alexander Maxiaguine <maxiagui@tik.ee.ethz.ch>\r
+\r
+ Computer Engineering and Networks Laboratory, TIK\r
+ Swiss Federal Institute of Technology, ETHZ Zurich \r
+ Switzerland\r
+\r
+**************************************************************************/\r
+\r
+/**************************************************************************\r
+ Change Log:\r
+\r
+ 14.03.06 -- creation\r
+\r
+**************************************************************************/\r
+\r
+#ifndef DOL_RP_IDS_H\r
+#define DOL_RP_IDS_H\r
+\r
+//----------------- REPORT IDs -------------------------- \r
+const int RP_ID_PARAMETER_PROBLEM = 5000;\r
+\r
+\r
+#endif\r
--- /dev/null
+/**************************************************************************\r
+ dol_sched_if.h\r
+ \r
+ Scheduler interface for a DOL process \r
+\r
+ (c) 2006 by Alexander Maxiaguine <maxiagui@tik.ee.ethz.ch>\r
+\r
+ Computer Engineering and Networks Laboratory, TIK\r
+ Swiss Federal Institute of Technology, ETHZ Zurich \r
+ Switzerland\r
+\r
+**************************************************************************/\r
+\r
+/**************************************************************************\r
+ Change Log:\r
+\r
+ 14.03.06 -- creation\r
+\r
+**************************************************************************/\r
+\r
+#ifndef DOL_SCHED_IF_H\r
+#define DOL_SCHED_IF_H\r
+\r
+#include "systemc.h"\r
+\r
+\r
+class dol_sched_if \r
+{\r
+\r
+public:\r
+ virtual void initialize() = 0;\r
+ virtual int fire() = 0;\r
+\r
+\r
+protected:\r
+ dol_sched_if() {}\r
+\r
+\r
+private:\r
+\r
+ // disabled\r
+ dol_sched_if( const dol_sched_if& );\r
+ dol_sched_if& operator = ( const dol_sched_if& );\r
+};\r
+\r
+#endif\r
--- /dev/null
+/*****************************************************************************
+
+ The following code is derived, directly or indirectly, from the SystemC
+ source code Copyright (c) 1996-2004 by all Contributors.
+ All Rights reserved.
+
+ The contents of this file are subject to the restrictions and limitations
+ set forth in the SystemC Open Source License Version 2.4 (the "License");
+ You may not use this file except in compliance with such restrictions and
+ limitations. You may obtain instructions on how to receive a copy of the
+ License at http://www.systemc.org/. Software distributed by Contributors
+ under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+ ANY KIND, either express or implied. See the License for the specific
+ language governing rights and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ simple_fifo.cpp -- Simple SystemC 2.0 producer/consumer example.
+
+ From "An Introduction to System Level Modeling in
+ SystemC 2.0". By Stuart Swan, Cadence Design Systems.
+ Available at www.systemc.org
+
+ Original Author: Stuart Swan, Cadence Design Systems, 2001-06-18
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+#ifndef _SIMPLE_FIFO_H_
+#define _SIMPLE_FIFO_H_
+
+#include <systemc.h>
+
+class write_if : virtual public sc_interface
+{
+ public:
+ virtual void write(char) = 0;
+ virtual void reset() = 0;
+ virtual int wtest(int) = 0;
+};
+
+class read_if : virtual public sc_interface
+{
+ public:
+ virtual void read(char &) = 0;
+ virtual int num_available() = 0;
+ virtual int rtest(int) = 0;
+};
+
+class fifo : public sc_channel, public write_if, public read_if
+{
+ public:
+ fifo(sc_module_name name, int size)
+ : sc_channel(name), num_elements(0), first(0), max(size) {
+ data = new char[size];
+ }
+
+ void write(char c) {
+ if (num_elements == max)
+ wait(read_event);
+
+ data[(first + num_elements) % max] = c;
+ ++ num_elements;
+ write_event.notify();
+ }
+
+ void read(char &c){
+ if (num_elements == 0)
+ wait(write_event);
+
+ c = data[first];
+ -- num_elements;
+ first = (first + 1) % max;
+ read_event.notify();
+ }
+
+ int rtest(int size) { return (size <= num_elements) ? 1 : 0; }
+ int wtest(int size) { return (size <= max - num_elements) ? 1 : 0; }
+
+
+ void reset() { num_elements = first = 0; }
+
+ int num_available() { return num_elements;}
+
+ private:
+ int max;
+ char *data;
+ int num_elements, first;
+ sc_event write_event, read_event;
+};
+
+
+#endif
+
+/*
+class producer : public sc_module
+{
+ public:
+ sc_port<write_if> out;
+
+ SC_HAS_PROCESS(producer);
+
+ producer(sc_module_name name) : sc_module(name)
+ {
+ SC_THREAD(main);
+ }
+
+ void main()
+ {
+ const char *str =
+ "Visit www.systemc.org and see what SystemC can do for you today!\n";
+
+ while (*str)
+ out->write(*str++);
+ }
+};
+
+class consumer : public sc_module
+{
+ public:
+ sc_port<read_if> in;
+
+ SC_HAS_PROCESS(consumer);
+
+ consumer(sc_module_name name) : sc_module(name)
+ {
+ SC_THREAD(main);
+ }
+
+ void main()
+ {
+ char c;
+ cout << endl << endl;
+
+ while (true) {
+ in->read(c);
+ cout << c << flush;
+
+ if (in->num_available() == 1)
+ cout << "<1>" << flush;
+ if (in->num_available() == 9)
+ cout << "<9>" << flush;
+ }
+ }
+};
+
+class top : public sc_module
+{
+ public:
+ fifo *fifo_inst;
+ producer *prod_inst;
+ consumer *cons_inst;
+
+ top(sc_module_name name) : sc_module(name)
+ {
+ fifo_inst = new fifo("Fifo1");
+
+ prod_inst = new producer("Producer1");
+ prod_inst->out(*fifo_inst);
+
+ cons_inst = new consumer("Consumer1");
+ cons_inst->in(*fifo_inst);
+ }
+};
+
+int sc_main (int argc , char *argv[]) {
+ top top1("Top1");
+ sc_start(-1);
+ return 0;
+}
+*/
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Code generator for SystemC functional simulation.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: MapXmlVisitor.java 1 2010-02-24 13:03:05Z haidw $ */\r
+package dol.visitor.xml;\r
+\r
+import dol.datamodel.XmlTag;\r
+import dol.datamodel.mapping.CommunicationBinding;\r
+import dol.datamodel.mapping.ComputationBinding;\r
+import dol.datamodel.mapping.Configuration;\r
+import dol.datamodel.mapping.Mapping;\r
+import dol.datamodel.mapping.Schedule;\r
+import dol.datamodel.mapping.ScheduleEntry;\r
+import dol.datamodel.mapping.SchedulingPolicy;\r
+import dol.datamodel.mapping.Variable;\r
+import dol.util.CodePrintString;\r
+import dol.visitor.MapVisitor;\r
+\r
+public class MapXmlVisitor extends MapVisitor {\r
+\r
+ /**\r
+ * Constructor.\r
+ *\r
+ * @param stringBuffer buffer where the result is stored\r
+ */\r
+ public MapXmlVisitor(StringBuffer stringBuffer) {\r
+ _ps = new CodePrintString(stringBuffer);\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param x mapping that needs to be rendered.\r
+ */\r
+ public void visitComponent(Mapping x) {\r
+ String xmlns = dol.util.SchemaLocation.\r
+ getMappingNamespace();\r
+ String xsiLocation = dol.util.SchemaLocation.\r
+ getMappingSchemaLocation();\r
+\r
+ _ps.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");\r
+ _ps.printOpeningTag(_xt.getMappingTag());\r
+ _ps.println(" xmlns=\"" + xmlns\r
+ + "\" xmlns:xsi=\"http://www.w3.org/2001/"\r
+ + "XMLSchema-instance\""\r
+ + System.getProperty("line.separator")\r
+ + " xsi:schemaLocation=\""\r
+ + xmlns + " " + xsiLocation + "\" name=\""\r
+ + x.getName() + "\">");\r
+\r
+ // Visit variables\r
+ for(Variable v : x.getVarList()) {\r
+ v.accept(this);\r
+ }\r
+\r
+ // Visit computation bindings\r
+ for(ComputationBinding b : x.getCompBindList()) {\r
+ b.accept(this);\r
+ }\r
+\r
+ // Visit communication bindings\r
+ for(CommunicationBinding b : x.getCommBindList()) {\r
+ b.accept(this);\r
+ }\r
+\r
+ // Visit schedules\r
+ for(Schedule s : x.getScheduleList()) {\r
+ s.accept(this);\r
+ }\r
+\r
+ _ps.printClosingTag(_xt.getMappingTag());\r
+ }\r
+\r
+ /**\r
+ * \r
+ */\r
+ public void visitComponent(ComputationBinding x) {\r
+ _ps.printOpeningTag(_xt.getBindingTag());\r
+ _ps.println(" name=\"" + x.getName()\r
+ + "\" xsi:type=\"computation\">");\r
+\r
+ // Process\r
+ _ps.printPrefix();\r
+ String s = "<" + _xt.getProcessTag()\r
+ + " name=\"" + x.getProcess().getName() + "\"/>";\r
+ _ps.println(s);\r
+\r
+ // Processor\r
+ _ps.printPrefix();\r
+ s = "<" + _xt.getProcessorTag()\r
+ + " name=\"" + x.getProcessor().getName() + "\"/>";\r
+ _ps.println(s);\r
+ _ps.printClosingTag(_xt.getBindingTag());\r
+ }\r
+\r
+ /**\r
+ * \r
+ */\r
+ public void visitComponent(CommunicationBinding x) {\r
+ _ps.printOpeningTag(_xt.getBindingTag());\r
+ _ps.println(" name=\"" + x.getName()\r
+ + "\" xsi:type=\"communication\">");\r
+\r
+ // SW channel\r
+ _ps.printPrefix();\r
+ String s = "<" + _xt.getSWChannelTag()\r
+ + " name=\"" + x.getChannel().getName() + "\"/>";\r
+ _ps.println(s);\r
+\r
+ // Write path\r
+ _ps.printPrefix();\r
+ s = "<" + _xt.getWritePathTag()\r
+ + " name=\"" + x.getWritePath().getName() + "\"/>";\r
+ _ps.println(s);\r
+\r
+ // Read path\r
+ _ps.printPrefix();\r
+ s = "<" + _xt.getReadPathTag()\r
+ + " name=\"" + x.getReadPath().getName() + "\"/>";\r
+ _ps.println(s);\r
+\r
+ _ps.printClosingTag(_xt.getBindingTag());\r
+ }\r
+\r
+ /**\r
+ * \r
+ */\r
+ public void visitComponent(Schedule x) {\r
+ _ps.printOpeningTag(_xt.getScheduleTag());\r
+ _ps.println(" name=\"" + x.getName()\r
+ + "\" type=\""\r
+ + SchedulingPolicy.toString(x.getSchedPolicy()) + "\">");\r
+\r
+ // Resource\r
+ _ps.printPrefix();\r
+ String s = "<" + _xt.getResourceTag()\r
+ + " name=\"" + x.getResource().getName() + "\"/>";\r
+ _ps.println(s);\r
+\r
+ // Scheduler table entries\r
+ for (ScheduleEntry p : x.getEntryList()) {\r
+ p.accept(this);\r
+ }\r
+\r
+ // Configuration of schedule\r
+ for (Configuration c : x.getCfgList()) {\r
+ c.accept(this);\r
+ }\r
+\r
+ _ps.printClosingTag(_xt.getScheduleTag());\r
+ }\r
+\r
+ /**\r
+ * \r
+ */\r
+ public void visitComponent(ScheduleEntry x) {\r
+ if (x.getCfgList().size() == 0) {\r
+ _ps.printPrefixln("<" + _xt.getOriginTag() + " name=\""\r
+ + x.getName() + "\"/>");\r
+ } else {\r
+ _ps.printOpeningTag(_xt.getOriginTag());\r
+ _ps.println(" name=\"" + x.getName() + "\">");\r
+ \r
+ // Configuration of the scheduler entry\r
+ for (Configuration c : x.getCfgList()) {\r
+ c.accept(this);\r
+ }\r
+\r
+ _ps.printClosingTag(_xt.getOriginTag());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * \r
+ */\r
+ public void visitComponent(Variable x) {\r
+ _ps.printPrefix();\r
+ String s = "<" + _xt.getVariableTag()\r
+ + " name=\"" + x.getName() + "\""\r
+ + " value=\"" + Integer.toString(x.getValue()) + "\"/>";\r
+ _ps.println(s);\r
+ }\r
+\r
+ /**\r
+ * \r
+ */\r
+ public void visitComponent(Configuration x) {\r
+ _ps.printPrefix();\r
+ String s = "<" + _xt.getConfigurationTag()\r
+ + " name=\"" + x.getName() + "\""\r
+ + " value=\"" + x.getValue() + "\"/>";\r
+ _ps.println(s);\r
+ }\r
+\r
+ protected CodePrintString _ps = null;\r
+ protected XmlTag _xt = XmlTag.getInstance();\r
+}\r
--- /dev/null
+/* $Id: PNXmlVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.xml;
+
+import dol.datamodel.XmlTag;
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Configuration;
+import dol.datamodel.pn.Connection;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.ProfilingConfiguration;
+import dol.datamodel.pn.SourceCode;
+import dol.util.CodePrintString;
+import dol.visitor.PNVisitor;
+
+/**
+ * This is a class for a visitor that is used to generate
+ * a schema compatible XML for process network.
+ */
+public class PNXmlVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ *
+ * @param stringBuffer buffer where the result is stored
+ */
+ public PNXmlVisitor(StringBuffer stringBuffer) {
+ _ps = new CodePrintString(stringBuffer);
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered.
+ */
+ public void visitComponent(ProcessNetwork x) {
+ String xmlns = dol.util.SchemaLocation.
+ getProcessNetworkNamespace();
+ String xsiLocation = dol.util.SchemaLocation.
+ getProcessNetworkSchemaLocation();
+
+
+ _ps.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ _ps.printOpeningTag(_xt.getPNTag());
+ _ps.println(" xmlns=\"" + xmlns
+ + "\" xmlns:xsi=\"http://www.w3.org/2001/"
+ + "XMLSchema-instance\""
+ + System.getProperty("line.separator")
+ + " xsi:schemaLocation=\""
+ + xmlns + " " + xsiLocation + "\" name=\""
+ + x.getName() + "_annotated" + "\">");
+
+ //visit all processes
+ for (Process p : x.getProcessList()) {
+ p.accept(this);
+ }
+ _ps.println();
+
+ //visit all channels
+ for (Channel c : x.getChannelList()) {
+ c.accept(this);
+ }
+ _ps.println();
+
+ //visit all connections
+ for (Connection n : x.getConnectionList()) {
+ n.accept(this);
+ }
+
+ _ps.printClosingTag(_xt.getPNTag());
+ }
+
+ /**
+ * Print a line for the process in the correct format for XML.
+ *
+ * @param x process that needs to be rendered
+ */
+ public void visitComponent(Process x) {
+ _ps.printOpeningTag(_xt.getProcessTag());
+ _ps.println(" name=\"" + x.getName()
+ + "\" basename=\"" + x.getBasename()
+ + "\" range=\"" + x.getRange()
+ + "\">");
+
+ for (Port p : x.getPortList()) {
+ p.accept(this);
+ }
+
+ for (SourceCode s : x.getSrcList()) {
+ s.accept(this);
+ }
+
+ for (Configuration c : x.getCfgList()) {
+ c.accept(this);
+ }
+
+ for (ProfilingConfiguration c : x.getProfilingList()) {
+ c.accept(this);
+ }
+
+ _ps.printClosingTag(_xt.getProcessTag());
+ }
+
+ /**
+ * Print a line for the channel in the correct format for XML.
+ *
+ * @param x channel that needs to be rendered
+ */
+ public void visitComponent(Channel x) {
+ _ps.printOpeningTag(_xt.getSWChannelTag());
+ _ps.println(" name=\"" + x.getName()
+ + "\" basename=\"" + x.getBasename()
+ + "\" type=\"" + x.getType()
+ + "\" size=\"" + x.getSize()
+ + "\">");
+
+ for (Port p : x.getPortList()) {
+ p.accept(this);
+ }
+
+ for (Configuration c : x.getCfgList()) {
+ c.accept(this);
+ }
+
+ for (ProfilingConfiguration c : x.getProfilingList()) {
+ c.accept(this);
+ }
+
+ _ps.printClosingTag(_xt.getSWChannelTag());
+ }
+
+ /**
+ * Print a line for the connection in the correct format for XML.
+ *
+ * @param x channel that needs to be rendered
+ */
+ public void visitComponent(Connection x) {
+ _ps.printOpeningTag(_xt.getConnectionTag());
+ _ps.println(" name=\"" + x.getName() + "\">");
+
+ //origin
+ _ps.printOpeningTag("origin");
+ _ps.println(" name=\"" + x.getOrigin().getName() + "\">");
+ _ps.println(" <port name=\""
+ + x.getOriginPort().getName() + "\"/>");
+ _ps.printClosingTag("origin");
+
+ //target
+ _ps.printOpeningTag("target");
+ _ps.println(" name=\"" + x.getTarget().getName() + "\">");
+ _ps.println(" <port name=\""
+ + x.getTargetPort().getName() + "\"/>");
+ _ps.printClosingTag("target");
+ _ps.printClosingTag("connection");
+ }
+
+ /**
+ * Print a line for the port in the correct format for XML.
+ *
+ * @param x port that needs to be rendered
+ */
+ public void visitComponent(Port x) {
+ _ps.printPrefix();
+ String s = "<" + _xt.getPortTag()
+ + " name=\"" + x.getName()
+ + "\" basename=\"" + x.getBasename()
+ + "\" range=\"" + x.getRange()
+ + "\"";
+ if (!x.getType().equals(""))
+ s += " type=\"" + x.getType() + "\"";
+ s += " />";
+
+ _ps.println(s);
+ }
+
+ /**
+ * Print a line for the source code in the correct format for XML.
+ *
+ * @param x source that needs to be rendered
+ */
+ public void visitComponent(SourceCode x) {
+ _ps.printPrefix();
+ _ps.println("<" + _xt.getSourceTag()
+ + " type=\"" + x.getType()
+ + "\" location=\"" + x.getLocality()
+ + "\" />");
+ }
+
+ /**
+ * Print a line for the configuration in the correct format for XML.
+ *
+ * @param x configuration that needs to be rendered
+ */
+ public void visitComponent(Configuration x) {
+ _ps.printPrefix();
+ _ps.println("<" + _xt.getConfigurationTag()
+ + " name=\"" + x.getName()
+ + "\" value=\"" + x.getValue()
+ + "\" />");
+ }
+
+ /**
+ * Print a line for the profiling configuration in the correct format for XML.
+ *
+ * @param x configuration that needs to be rendered
+ */
+ public void visitComponent(ProfilingConfiguration x) {
+ _ps.printPrefix();
+ _ps.println("<" + _xt.getProfilingTag()
+ + " name=\"" + x.getName()
+ + "\" value=\"" + x.getValue()
+ + "\" />");
+ }
+
+ protected CodePrintString _ps = null;
+
+ protected XmlTag _xt = XmlTag.getInstance();
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Schema compatible XML generator for process network.
+
+Maybe for architecture and mapping in the future.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+/* $Id: YapiMakefileVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.yapi;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class YapiMakefileVisitor extends PNVisitor {
+
+ /**
+ *
+ */
+ public YapiMakefileVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ String filename = _dir + _delimiter + "Makefile";
+ OutputStream file = new FileOutputStream(filename);
+ PrintStream ps = new PrintStream(file);
+ ps.println("YAPI = /lib/yapi");
+ ps.println("INCLUDES = -I$(YAPI)/include -Iwrappers -Ilib -Iprocesses -I.");
+ ps.println("LIBS = $(YAPI)/lib/libyapi.a");
+ ps.println("CXX = g++");
+ ps.println("CXXFLAGS = -g -Wall -O $(INCLUDES)");
+ ps.println("OBJS = application.o \\");
+ Vector<String> processList = new Vector<String>();
+ for (Process p : pn.getProcessList()) {
+ String basename = p.getBasename();
+ if (!processList.contains(basename)) {
+ processList.add(basename);
+ ps.println(" wrappers/" + p.getBasename()
+ + "_wrapper.o \\");
+ }
+ }
+ ps.println(" lib/dolSupport.o \\");
+ ps.println(" lib/ProcessWrapper.o \\");
+ ps.println(" lib/main.o");
+ ps.println();
+ ps.println("EXE = ./sc_application");
+ ps.println();
+ ps.println("all : $(EXE)");
+ ps.println();
+ ps.println("test : $(EXE)");
+ ps.println("\t@$(EXE)");
+ ps.println();
+ ps.println("$(EXE) : $(OBJS)");
+ ps.println("\t$(CXX) $(LDFLAGS) $(OBJS) $(LIBS) -o $(EXE)");
+ ps.println();
+ ps.println("clean : ;");
+ ps.println("\trm -rf $(OBJS) $(EXE)");
+ }
+ catch (IOException e) {
+ System.out.println(" Yapi Makefile Visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected String _dir = null;
+ protected String _name = "sc_application";
+}
+
--- /dev/null
+/* $Id: YapiModuleVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.yapi;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Channel;
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.CodePrintStream;
+import dol.visitor.PNVisitor;
+
+/**
+ * This class is a class for a visitor that is used to generate
+ * the main program.
+ */
+public class YapiModuleVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public YapiModuleVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ //create header file
+ String filename = _dir + _delimiter + "application.h";
+ OutputStream file = new FileOutputStream(filename);
+ _code = new CodePrintStream(file);
+
+ _code.println("#include \"yapi.h\"");
+ _code.println();
+
+ Vector<String> processList = new Vector<String>();
+ for (Process p : pn.getProcessList()) {
+ String basename = p.getBasename();
+ if (!processList.contains(basename)) {
+ processList.add(basename);
+ _code.println("#include \""
+ + p.getBasename() + "_wrapper.h\"");
+ }
+ }
+ _code.println();
+ _code.println("class Application : public ProcessNetwork");
+ _code.println("{");
+ _code.println("public:");
+ _code.println(" Application(const Id& n);");
+ _code.println(" const char* type() const;");
+ _code.println();
+ _code.println("private:");
+
+ for (Channel c : pn.getChannelList()) {
+ if (c.getType().equals("fifo")) {
+ _code.println(" Fifo<char> " + c.getName()
+ + ";");
+ } else if (c.getType().equals("wfifo")) {
+ System.out.println("Warning: YAPI visitor does not "
+ + "support windowed FIFOs.");
+ }
+ }
+ _code.println();
+
+ for (Process p : pn.getProcessList()) {
+ _code.println(" " + p.getBasename() + "_wrapper "
+ + p.getName() + ";");
+ }
+ _code.println("};");
+ file.close();
+
+
+ //create cpp file
+ filename = _dir + _delimiter + "application.cpp";
+ file = new FileOutputStream(filename);
+ _code = new CodePrintStream(file);
+
+ _code.println("#include \"application.h\"");
+ _code.println();
+ _code.println("Application::Application(const Id& n) :");
+ _code.print(" ProcessNetwork(n)");
+ for (Channel c : pn.getChannelList()) {
+ if (c.getType().equals("fifo")) {
+ _code.print(",\n " + c.getName() + "(id(\""
+ + c.getName() + "\"))");
+ } else if (c.getType().equals("wfifo")) {
+ System.out.println("Warning: YAPI visitor does not "
+ + "support windowed FIFOs.");
+ }
+ }
+ for (Process p : pn.getProcessList()) {
+ _code.print(",\n " + p.getName() + "(\""
+ + p.getName() + "\", id(\"" + p.getName()
+ + "\")");
+
+ for (Port port : p.getPortList()) {
+ _code.print(", " + port.getPeerResource().getName());
+ }
+ _code.print(")");
+ }
+ _code.println();
+ _code.println("{ }");
+ _code.println();
+ _code.println("const char* Application::type() const");
+ _code.println("{");
+ _code.println(" return \"Application\";");
+ _code.println("}");
+ }
+ catch (Exception e) {
+ System.out.println("YapiModuleVisitor: "
+ + "exception occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ protected CodePrintStream _code = null;
+ protected String _dir = null;
+ protected OutputStream _file;
+ protected CodePrintStream _pn;
+}
+
--- /dev/null
+/* $Id: YapiProcessVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.yapi;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import dol.datamodel.pn.Port;
+import dol.datamodel.pn.Process;
+import dol.datamodel.pn.ProcessNetwork;
+import dol.datamodel.pn.SourceCode;
+import dol.util.CodePrintStream;
+import dol.util.Sed;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class YapiProcessVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public YapiProcessVisitor(String dir) {
+ _dir = dir;
+ }
+
+ /**
+ *
+ * @param x process network that needs to be rendered
+ */
+ public void visitComponent(ProcessNetwork x) {
+ try {
+ Vector<String> pList = new Vector<String>();
+
+ for (Process p : x.getProcessList()) {
+ String basename = p.getBasename();
+ if (!pList.contains(basename)) {
+ pList.add(basename);
+ p.accept(this);
+ }
+ }
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @param p process that needs to be rendered
+ */
+ public void visitComponent(Process p) {
+ try {
+ _createCppFile(p);
+ _createHeaderFile(p);
+ _adaptSources(p);
+ }
+ catch (Exception e) {
+ System.out.println("Process Visitor: exception "
+ + "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _adaptSources(Process p) throws IOException {
+ Sed sed = new Sed();
+ for (Port port : p.getPortList()) {
+ String processHeaderFile;
+
+ for (SourceCode sr : p.getSrcList()) {
+ processHeaderFile = _dir + _delimiter + ".."
+ + _delimiter + "processes" + _delimiter
+ + sr.getLocality().
+ replaceAll("(.*)\\.[cC][pP]*[pP]*", "$1\\.h");
+
+ if (port.isOutPort()) {
+ sed.sed(processHeaderFile,
+ "(#define[ ]*PORT_\\w*[ ]*)\"?"
+ + port.getBasename() + "\"?",
+ "$1 " + "(const_cast<void *>((const void*)"
+ +"(((static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))->OUTPORT_"
+ + port.getBasename() + "))))");
+ }
+ else if (port.isInPort()) {
+ sed.sed(processHeaderFile,
+ "(#define[ ]*PORT_\\w*[ ]*)\"?"
+ + port.getBasename() + "\"?",
+ "$1 " + "(const_cast<void *>((const void*)"
+ +"(((static_cast<" + p.getBasename()
+ + "_wrapper *>(p->wptr))->INPORT_"
+ + port.getBasename() + "))))");
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ protected void _createCppFile(Process p) throws IOException {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.cpp";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ String newline = System.getProperty("line.separator");
+ String code = "#include \"" + p.getBasename() + "_wrapper.h\""
+ + newline;
+ code += "#include \"dolSupport.h\"" + newline;
+ for (SourceCode sr : p.getSrcList()) {
+ code += "#include \"" + sr.getLocality() + "\"" + newline;
+ }
+
+ code += newline;
+
+ code += p.getBasename() + "_wrapper::" + p.getBasename()
+ + "_wrapper(const char* name, const Id& n";
+ for (Port port : p.getPortList()) {
+ if (port.isInPort()) {
+ code += ", In<char>& inport_" + port.getName();
+ } else {
+ code += ", Out<char>& outport_" + port.getName();
+ }
+ }
+ code += ")" + newline;
+
+ code += " : ProcessWrapper(name, n)" + newline;
+ code += " {" + newline;
+ code += " _state = (LocalState)new "
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State;"
+ + newline;
+ code += " _process.local = _state;" + newline;
+ code += " _process.init = " + p.getBasename() + "_init;"
+ + newline;
+ code += " _process.fire = " + p.getBasename() + "_fire;"
+ + newline;
+ code += " _process.wptr = this;" + newline;
+ for (Port port : p.getPortList()) {
+ if (!port.getRange().equals("")) {
+ String portName =
+ port.getName().replaceAll("_([0-9])", "][$1");
+ portName += "]";
+ portName = portName.replaceFirst("]", "");
+ if (port.isOutPort()) {
+ code += " OUTPORT_" + portName
+ + " = new OutPort<char>(id(\"" + port.getName()
+ + "\"), outport_" + port.getName() + ");"
+ + newline;
+ }
+ else if (port.isInPort()) {
+ code += " INPORT_" + portName
+ + " = new InPort<char>(id(\"" + port.getName()
+ + "\"), inport_" + port.getName() + ");"
+ + newline;
+ }
+ } else {
+ if (port.isInPort()) {
+ code += " INPORT_" + port.getName()
+ + " = new InPort<char>(id(\"" + port.getName()
+ + "\"), inport_" + port.getName() + ");"
+ + newline;
+ } else {
+ code += " OUTPORT_" + port.getName()
+ + " = new OutPort<char>(id(\"" + port.getName()
+ + "\"), outport_" + port.getName() + ");"
+ + newline;
+ }
+ }
+ }
+ code += "}" + newline + newline;
+
+ code += p.getBasename() + "_wrapper::~" + p.getBasename()
+ + "_wrapper() {" + newline;
+ code += " if (_state)" + newline;
+ code += " delete ("
+ + p.getBasename().substring(0, 1).toUpperCase()
+ + p.getBasename().substring(1) + "_State*)_state;"
+ + newline;
+ for (Port port : p.getPortList()) {
+ if (!port.getRange().equals("")) {
+ String portName =
+ port.getName().replaceAll("_([0-9])", "][$1");
+ portName += "]";
+ portName = portName.replaceFirst("]", "");
+ if (port.isOutPort()) {
+ code += " if (OUTPORT_" + portName + ")" + newline;
+ code += " delete OUTPORT_" + portName + ";"
+ + newline;
+ }
+ else if (port.isInPort()) {
+ code += " if (INPORT_" + portName + ")" + newline;
+ code += " delete INPORT_" + portName + ";"
+ + newline;
+ }
+ } else {
+ if (port.isInPort()) {
+ code += " if(INPORT_" + port.getName() + ")"
+ + newline;
+ code += " delete INPORT_" + port.getName() + ";"
+ + newline;
+ } else {
+ code += " if(OUTPORT_" + port.getName() + ")"
+ + newline;
+ code += " delete OUTPORT_" + port.getName() + ";"
+ + newline;
+ }
+ }
+ }
+ code += "}" + newline + newline;
+
+ code += "const char* "
+ + p.getBasename() + "_wrapper::type() const {" + newline;
+ code += " return \"" + p.getName() + "\";" + newline;
+ code += "}" + newline + newline;
+
+ code += "void " + p.getBasename() + "_wrapper::main() {" + newline;
+ code += " _process.init(&_process);" + newline;
+ code += " while(!isDetached()) {" + newline;
+ code += " _process.fire(&_process);" + newline;
+ code += " }" + newline;
+ code += "}" + newline;
+ ps.printPrefixln(code);
+ }
+
+ protected void _createHeaderFile(Process p)
+ throws IOException {
+ String filename = _dir + _delimiter + p.getBasename()
+ + "_wrapper.h";
+ OutputStream file = new FileOutputStream(filename);
+ CodePrintStream ps = new CodePrintStream(file);
+
+ String newline = System.getProperty("line.separator");
+ String code = "#ifndef " + p.getBasename() + "_WRAPPER_H"
+ + newline;
+ code += "#define " + p.getBasename() + "_WRAPPER_H" + newline
+ + newline;
+ code += "#include \"ProcessWrapper.h\"" + newline;
+ code += newline;
+
+ code += "class " + p.getBasename() + "_wrapper : "
+ + "public ProcessWrapper {" + newline;
+ code += " public:" + newline;
+ code += " " + p.getBasename()
+ + "_wrapper(const char* name, const Id& n";
+ for (Port port : p.getPortList()) {
+ if (port.isInPort()) {
+ code += ", In<char>& inport_" + port.getName();
+ } else {
+ code += ", Out<char>& outport_" + port.getName();
+ }
+ }
+ code += ");" + newline;
+ code += " virtual ~" + p.getBasename() + "_wrapper();"
+ + newline;
+ code += " const char* type() const;" + newline;
+ code += " void main();" + newline + newline;
+
+ Vector<String> portList = new Vector<String>();
+ for (Port port : p.getPortList()) {
+ String basename = port.getBasename();
+
+ if (!portList.contains(basename)) {
+ portList.add(basename);
+
+ if (!port.getRange().equals("")) {
+ if (port.isOutPort()) {
+ code += " OutPort<char> *OUTPORT_"
+ + port.getBasename() + "["
+ + port.getRange().replaceAll(
+ ";", "\\]\\[") + "];" + newline;
+ }
+ else if (port.isInPort()) {
+ code += " InPort<char> *INPORT_"
+ + port.getBasename() + "["
+ + port.getRange().replaceAll(
+ ";", "\\]\\[") + "];" + newline;
+ }
+ }
+ else {
+ if (port.isOutPort()) {
+ code += " OutPort<char> *OUTPORT_"
+ + port.getName() + ";" + newline;
+ }
+ else if (port.isInPort()) {
+ code += " InPort<char> *INPORT_"
+ + port.getName() + ";" + newline;
+ }
+ }
+ }
+ }
+ code += newline;
+ code += " protected:" + newline;
+ code += " LocalState _state;" + newline;
+ code += "};" + newline + newline;
+ code += "#endif";
+ ps.printPrefixln(code);
+ }
+
+ protected String _dir = null;
+}
--- /dev/null
+/* $Id: YapiVisitor.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.visitor.yapi;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import dol.datamodel.pn.ProcessNetwork;
+import dol.util.Copier;
+import dol.visitor.PNVisitor;
+
+/**
+ *
+ */
+public class YapiVisitor extends PNVisitor {
+
+ /**
+ * Constructor.
+ */
+ public YapiVisitor(String packageName) {
+ _packageName = packageName;
+ }
+
+ /**
+ *
+ */
+ public void visitComponent(ProcessNetwork pn) {
+ try {
+ _generateDirHierarchy();
+
+ pn.accept(new YapiMakefileVisitor(_srcDir));
+ pn.accept(new YapiModuleVisitor(_srcDir));
+ pn.accept(new YapiProcessVisitor(_wrapperDir));
+
+ } catch (Exception e) {
+ System.out.println(" SystemC PN Visitor: exception " +
+ "occured: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ private void _generateDirHierarchy()
+ throws IOException, FileNotFoundException {
+
+ File dir = new File(_packageName);
+ dir.mkdirs();
+
+ _srcDir = _packageName + _delimiter + _srcDirName;
+ dir = new File(_srcDir);
+ dir.mkdirs();
+
+ _libDir = _srcDir + _delimiter + _libDirName;
+ dir = new File(_libDir);
+ dir.mkdirs();
+
+ _processDir = _srcDir + _delimiter + _processDirName;
+ dir = new File(_processDir);
+ dir.mkdirs();
+
+ _wrapperDir = _srcDir + _delimiter + _wrapperDirName;
+ dir = new File(_wrapperDir);
+ dir.mkdirs();
+
+ // copy library
+ String libraryPath = _ui.getMySystemCLib();
+ libraryPath = libraryPath.replaceAll("systemC",
+ "yapi");
+ File source = new File(libraryPath);
+ File destination = new File(_libDir);
+ new Copier().copy(source, destination);
+
+ //copy process src code
+ source = new File(_srcDirName);
+ destination = new File(_processDir);
+ new Copier().copy(source, destination);
+ }
+
+ protected String _packageName = null;
+
+ protected String _srcDir = "";
+ protected static String _srcDirName = "src";
+
+ protected String _libDir = "";
+ protected static String _libDirName = "lib";
+
+ protected String _processDir = "";
+ protected static String _processDirName = "processes";
+
+ protected String _wrapperDir = "";
+ protected static String _wrapperDirName = "wrappers";
+}
+
--- /dev/null
+#include "ProcessWrapper.h"\r
+#include "dolSupport.h"\r
+\r
+/**\r
+ *\r
+ */\r
+ProcessWrapper::ProcessWrapper(const char* name, const Id& n) : Process(n) {\r
+ _name = new char[strlen(name) + 1];\r
+ strcpy(_name, name);\r
+\r
+ _isDetached = false;\r
+ for (int i = 0; i < 4; i++) {\r
+ _iteratorIndex[i] = getIndex(_name, "_", i);\r
+ }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+ProcessWrapper::~ProcessWrapper() {\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ProcessWrapper::initialize() {\r
+ _process.init(&_process);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+int ProcessWrapper::fire()\r
+{\r
+ return _process.fire(&_process);\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void ProcessWrapper::detach() {\r
+ _isDetached = true;\r
+}\r
+\r
+\r
+/**\r
+ * Gets an index of a string, where the index must be separated by\r
+ * a character specified in tokens.\r
+ * Returns -1, when an error occurs.\r
+ *\r
+ * Example:\r
+ * getIndex("name_1_2", "_", 0) will return 1.\r
+ * getIndex("name_1_2", "_", 1) will return 2.\r
+ *\r
+ * @param string string to parse\r
+ * @param tokens delimiter of indices\r
+ * @param indexNumber position of index (starting at 0)\r
+ */\r
+int ProcessWrapper::getIndex(const char* string, char* tokens,\r
+ int indexNumber) const {\r
+ char* string_copy;\r
+ char* token_pointer;\r
+ int index = 0;\r
+\r
+ string_copy = (char*) malloc(sizeof(char) * (strlen(string) + 1));\r
+ if (!string_copy) {\r
+ fprintf(stderr, "getIndex(): could not allocate memory.\n");\r
+ return -1;\r
+ }\r
+\r
+ strcpy(string_copy, string);\r
+\r
+ token_pointer = strtok(string_copy, tokens);\r
+ do {\r
+ token_pointer = strtok(NULL, tokens);\r
+ index++;\r
+ } while (index <= indexNumber && token_pointer != 0);\r
+\r
+ if (token_pointer) {\r
+ index = atoi(token_pointer);\r
+ free(string_copy);\r
+ return index;\r
+ }\r
+\r
+ return -1;\r
+}\r
+\r
+\r
+/**\r
+ * Get the name of this process.\r
+ */\r
+char* ProcessWrapper::getName() const {\r
+ return _name;\r
+}\r
+\r
+\r
+/**\r
+ * Get the index of this process.\r
+ * @param indexNumber position of index (starting at 0)\r
+ */\r
+int ProcessWrapper::getIndex(unsigned indexNumber) const {\r
+ if (indexNumber < 4) {\r
+ return _iteratorIndex[indexNumber];\r
+ }\r
+ return -1;\r
+}\r
--- /dev/null
+#ifndef _PROCESSWRAPPER_H_\r
+#define _PROCESSWRAPPER_H_\r
+\r
+#include "dol.h"\r
+#include "yapi.h"\r
+\r
+class ProcessWrapper : public Process\r
+{\r
+ public:\r
+ ProcessWrapper(const char* name, const Id& n);\r
+ virtual ~ProcessWrapper();\r
+ virtual void initialize();\r
+ virtual int fire();\r
+ virtual bool isDetached() const { return _isDetached; }\r
+ virtual void detach();\r
+ virtual int getIndex(unsigned indexNumber) const;\r
+ virtual char* getName() const;\r
+\r
+ protected:\r
+ char* _name;\r
+ DOLProcess _process;\r
+ bool _isDetached;\r
+ int _iteratorIndex[4];\r
+ virtual int getIndex(const char* string, char* tokens,\r
+ int indexNumber) const;\r
+};\r
+\r
+#endif\r
+\r
--- /dev/null
+#ifndef DOL_H
+#define DOL_H
+
+/************************************************************************
+ * do not add code to this header
+ ************************************************************************/
+
+/**
+ * Define the DOL process handler scheme.
+ * - Local variables are defined in structure LocalState. Local
+ * variables may vary from different processes.
+ * - The ProcessInit function pointer points to a function which
+ * initializes a process.
+ * - The ProcessFire function pointer points to a function which
+ * performs the actual computation. The communication between
+ * processes is inside the ProcessFire function.
+ * - The WPTR is a placeholder for callback. One can just
+ * leave it blank.
+ */
+
+//structure for local memory of process
+typedef struct _local_states *LocalState;
+
+//additional behavioral functions could be declared here
+typedef void (*ProcessInit)(struct _process*);
+typedef int (*ProcessFire)(struct _process*);
+typedef void *WPTR;
+
+//process handler
+struct _process;
+
+typedef struct _process {
+ LocalState local;
+ ProcessInit init;
+ ProcessFire fire;
+ WPTR wptr; //placeholder for wrapper instance
+} DOLProcess;
+
+#endif
--- /dev/null
+#include "dolSupport.h"\r
+#include "ProcessWrapper.h"\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned dolwrite(OutPort<char> *out, const void *buf, unsigned len, const DOLProcess *process)\r
+{\r
+ write(*out, (char*)buf, len);\r
+ return len;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned dolread(InPort<char> *in, const void *buf, unsigned len, const DOLProcess *process) {\r
+ read(*in, (char*)buf, len);\r
+ return len;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void DOL_detach(DOLProcess* p) {\r
+ static_cast<ProcessWrapper *>(p->wptr)->detach();\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0) {\r
+ *port = (void**)((void**)base)[index0];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1) {\r
+ *port = (void**)((void**)base)[index0 * range1 + index1];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2) {\r
+ *port = (void**)((void**)base)[index0 * range1 * range2\r
+ + index1 * range2 + index2];\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void createPort(void** port,\r
+ void* base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2,\r
+ int index3, int range3) {\r
+ *port = (void**)((void**)base)[index0 * range1 * range2 * range3\r
+ + index1 * range2 * range3\r
+ + index2 * range3\r
+ + index3];\r
+}\r
--- /dev/null
+#ifndef DOLSUPPORT_H\r
+#define DOLSUPPORT_H\r
+\r
+#include "dol.h"\r
+#include "yapi.h"\r
+\r
+#define DOL_write(port, buf, len, process) \\r
+ dolwrite(static_cast<OutPort<char> *>(port), buf, len, process)\r
+#define DOL_read(port, buf, len, process) \\r
+ dolread(static_cast<InPort<char> *>(port), buf, len, process)\r
+\r
+void DOL_detach(DOLProcess* p);\r
+\r
+//fifo access functions\r
+unsigned dolwrite(OutPort<char> *out, const void *buf, unsigned len, const DOLProcess *process);\r
+unsigned dolread(InPort<char> *in, const void *buf, unsigned len, const DOLProcess *process);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2);\r
+\r
+void createPort(void **port,\r
+ void *base,\r
+ int number_of_indices,\r
+ int index0, int range0,\r
+ int index1, int range1,\r
+ int index2, int range2,\r
+ int index3, int range3);\r
+\r
+#define GETINDEX(dimension) \\r
+ static_cast<ProcessWrapper *>(p->wptr)->getIndex(dimension)\r
+\r
+/**\r
+ * macro to create a variable to store a port name\r
+ *\r
+ * @param name name of the variable\r
+ */\r
+#define CREATEPORTVAR(name) void *name\r
+\r
+/**\r
+ * Create the port name of an iterated port based on its basename and the\r
+ * given indices.\r
+ *\r
+ * @param port buffer where the result is stored (created using\r
+ * CREATEPORTVAR)\r
+ * @param base basename of the port\r
+ * @param number_of_indices number of dimensions of the port\r
+ * @param index_range_pairs index and range values for each dimension\r
+ */\r
+#define CREATEPORT(port, base, number_of_indices, index_range_pairs...) \\r
+ createPort((void**)(&port), base, number_of_indices, index_range_pairs)\r
+\r
+#endif\r
--- /dev/null
+#include "yapi.h"
+#include "application.h"
+#include <fstream>
+
+using namespace std;
+
+int main()
+{
+ // create yapi run-time environment
+ RTE rte;
+
+ // redirect standard output
+ ofstream f("./app.out");
+ rte.setOutStream(f);
+
+ // redirect standard error
+ ofstream g("./app.err");
+ rte.setErrorStream(g);
+
+ // create toplevel process network
+ Application app(id("app"));
+
+ // start the process network and
+ // wait for processes to finish
+ rte.start(app);
+
+ // print workload
+ ofstream h("./appworkload.txt");
+ printWorkload(app, h);
+
+ // generate dotty file
+ ofstream i("./app.dot");
+ printDotty(app, i);
+
+ f.close();
+ g.close();
+ h.close();
+ i.close();
+
+ return 0;
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+Code generator for YAPI functional simulation.
+
+<h2>Package Specification</h2>
+
+<!-- use ordinary html here -->
+
+<h2>Related Documentation</h2>
+
+<!-- use ordinary html here -->
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>
--- /dev/null
+# template for dol.properties file
+# use ant config to fill in the values
+
+# DOL path:
+# path to local directory of DOL
+#
+# example:
+# DOL_PATH = /home/shapes/dol
+
+DOL_path = @dol_path@
+
+# SystemC library path:
+# SYSTEMC_INC and SYSTEMC_LIB are the paths to SystemC header and library,
+# respectively. These two path will be used in the generated
+# Makefile to build the SystemC executable binary file.
+# They have to point to local SystemC directory.
+#
+# example:
+# SYSTEMC_INC = /home/shapes/base/resources/lib/systemC/systemc-2.1.v1/include
+# SYSTEMC_LIB = /home/shapes/base/resources/lib/systemC/systemc-2.1.v1/lib-linux/libsystemc.a
+
+SYSTEMC_INC = @systemc_inc@
+SYSTEMC_LIB = @systemc_lib@
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+\r
+<project name="runtest" default="runtest" basedir=".">\r
+\r
+ <description>\r
+ Ant build file for automated testing of DOL.\r
+ </description>\r
+\r
+ <property name="test.dir" location="dolzip"/>\r
+ <property name="test.resource.dir" location="${test.dir}/test"/>\r
+ <property name="test.src.dir" location="${test.resource.dir}/src"/>\r
+ <property name="test.reference.dir" location="${test.resource.dir}/reference"/>\r
+ <property name="build.main.dir" location="${test.dir}/build/bin/main"/>\r
+ <property name="jars.dir" location="${test.dir}/bin"/>\r
+ <property name="jars" value=".:${jars.dir}/jdom.jar:${jars.dir}/xercesImpl.jar"/>\r
+ <property name="systemc.inc" value="/home/shapes/base/resources/lib/systemC/include"/>\r
+ <property name="systemc.lib" value="/home/shapes/base/resources/lib/systemC/lib-linux/libsystemc.a"/>\r
+ \r
+ <target name="clean">\r
+ <delete dir="${test.dir}"/>\r
+ </target>\r
+\r
+ <!-- copy dol_ethz.zip to test and unzip -->\r
+ <target name="unzipandcompiledol">\r
+ <mkdir dir="${test.dir}"/>\r
+ <unzip src="dol_ethz.zip" dest="${test.dir}"/>\r
+ <copy file="${test.dir}/build_zip.xml" tofile="${test.dir}/build_zip_temp.xml">\r
+ <filterchain>\r
+ <tokenfilter>\r
+ <replaceregex pattern="/home/shapes/base/resources/lib/systemC/include"\r
+ replace="${systemc.inc}"\r
+ flags="g"/>\r
+ </tokenfilter>\r
+ <tokenfilter>\r
+ <replaceregex pattern="/home/shapes/base/resources/lib/systemC/lib-linux/libsystemc.a"\r
+ replace="${systemc.lib}"\r
+ flags="g"/>\r
+ </tokenfilter>\r
+ </filterchain>\r
+ </copy>\r
+ <move file="${test.dir}/build_zip_temp.xml" tofile="${test.dir}/build_zip.xml"/>\r
+ <ant antfile="build_zip.xml"\r
+ dir="${test.dir}"\r
+ target="all"\r
+ inheritAll="false"/>\r
+ </target>\r
+ \r
+ <!-- get resources required for testing -->\r
+ <target name="preparetest">\r
+ <exec executable="svn">\r
+ <arg line="export --no-auth-cache --username tec file:///home/shapes/base/SVNTree/dolPrototype/trunk/test ${test.resource.dir}"/>\r
+ </exec>\r
+\r
+ <javac destdir="${build.main.dir}" debug="true" classpath="${jars}">\r
+ <src path="${test.src.dir}"/>\r
+ </javac>\r
+ <copy todir="${build.main.dir}" file="${test.resource.dir}/runtests.xml"/>\r
+ <copy todir="${build.main.dir}" file="${test.resource.dir}/test.properties">\r
+ <filterchain>\r
+ <replacetokens>\r
+ <token key="schema_path" value="${test.dir}/schema"/>\r
+ </replacetokens>\r
+ </filterchain>\r
+ </copy>\r
+ </target>\r
+\r
+ <!-- run tests (uses runtests.xml and runexample.xml in ${build.main.dir}) -->\r
+ <target name="runtest" depends="unzipandcompiledol, preparetest">\r
+ <ant antfile="runtests.xml"\r
+ dir="${build.main.dir}"\r
+ target="xml"\r
+ inheritAll="false"/>\r
+ <ant antfile="runtests.xml"\r
+ dir="${build.main.dir}"\r
+ target="checkexamples"\r
+ inheritAll="false"/>\r
+ </target>\r
+</project>\r
--- /dev/null
+consumer: 0.000000
+consumer: 1.000000
+consumer: 4.000000
+consumer: 9.000000
+consumer: 16.000000
+consumer: 25.000000
+consumer: 36.000000
+consumer: 49.000000
+consumer: 64.000000
+consumer: 81.000000
+consumer: 100.000000
+consumer: 121.000000
+consumer: 144.000000
+consumer: 169.000000
+consumer: 196.000000
+consumer: 225.000000
+consumer: 256.000000
+consumer: 289.000000
+consumer: 324.000000
+consumer: 361.000000
--- /dev/null
+consumer: 0.000000
+consumer: 1.000000
+consumer: 4.000000
+consumer: 9.000000
+consumer: 16.000000
+consumer: 25.000000
+consumer: 36.000000
+consumer: 49.000000
+consumer: 64.000000
+consumer: 81.000000
+consumer: 100.000000
+consumer: 121.000000
+consumer: 144.000000
+consumer: 169.000000
+consumer: 196.000000
+consumer: 225.000000
+consumer: 256.000000
+consumer: 289.000000
+consumer: 324.000000
+consumer: 361.000000
--- /dev/null
+consumer: 0.000000
+consumer: 1.000000
+consumer: 256.000000
+consumer: 6561.000000
+consumer: 65536.000000
+consumer: 390625.000000
+consumer: 1679616.000000
+consumer: 5764801.000000
+consumer: 16777216.000000
+consumer: 43046720.000000
+consumer: 100000000.000000
+consumer: 214358880.000000
+consumer: 429981696.000000
+consumer: 815730752.000000
+consumer: 1475789056.000000
+consumer: 2562890752.000000
+consumer: 4294967296.000000
+consumer: 6975757312.000000
+consumer: 11019960320.000000
+consumer: 16983563264.000000
--- /dev/null
+consumer: 0.000000
+consumer: 1.000000
+consumer: 256.000000
+consumer: 6561.000000
+consumer: 65536.000000
+consumer: 390625.000000
+consumer: 1679616.000000
+consumer: 5764801.000000
+consumer: 16777216.000000
+consumer: 43046720.000000
+consumer: 100000000.000000
+consumer: 214358880.000000
+consumer: 429981696.000000
+consumer: 815730752.000000
+consumer: 1475789056.000000
+consumer: 2562890752.000000
+consumer: 4294967296.000000
+consumer: 6975757312.000000
+consumer: 11019960320.000000
+consumer: 16983563264.000000
--- /dev/null
+v_consumer: a
+v_consumer: a
+h_consumer: n
+h_consumer: n
+h_consumer: n
+v_consumer: a
+v_consumer: b
+v_consumer: b
+h_consumer: o
+h_consumer: o
+h_consumer: o
+v_consumer: b
+v_consumer: c
+v_consumer: c
+h_consumer: p
+h_consumer: p
+h_consumer: p
+v_consumer: c
+v_consumer: d
+v_consumer: d
+h_consumer: q
+h_consumer: q
+h_consumer: q
+v_consumer: d
+v_consumer: e
+v_consumer: e
+h_consumer: r
+h_consumer: r
+h_consumer: r
+v_consumer: e
+v_consumer: f
+v_consumer: f
+h_consumer: s
+h_consumer: s
+h_consumer: s
+v_consumer: f
+v_consumer: g
+v_consumer: g
+h_consumer: t
+h_consumer: t
+h_consumer: t
+v_consumer: g
+v_consumer: h
+v_consumer: h
+h_consumer: u
+h_consumer: u
+h_consumer: u
+v_consumer: h
+v_consumer: i
+v_consumer: i
+h_consumer: v
+h_consumer: v
+h_consumer: v
+v_consumer: i
+v_consumer: j
+v_consumer: j
+h_consumer: w
+h_consumer: w
+h_consumer: w
+v_consumer: j
+v_consumer: k
+v_consumer: k
+h_consumer: x
+h_consumer: x
+h_consumer: x
+v_consumer: k
+v_consumer: l
+v_consumer: l
+h_consumer: y
+h_consumer: y
+h_consumer: y
+v_consumer: l
+v_consumer: m
+v_consumer: m
+h_consumer: z
+h_consumer: z
+h_consumer: z
+v_consumer: m
--- /dev/null
+v_consumer: a
+v_consumer: a
+h_consumer: n
+h_consumer: n
+h_consumer: n
+v_consumer: a
+v_consumer: b
+v_consumer: b
+h_consumer: o
+h_consumer: o
+h_consumer: o
+v_consumer: b
+v_consumer: c
+v_consumer: c
+h_consumer: p
+h_consumer: p
+h_consumer: p
+v_consumer: c
+v_consumer: d
+v_consumer: d
+h_consumer: q
+h_consumer: q
+h_consumer: q
+v_consumer: d
+v_consumer: e
+v_consumer: e
+h_consumer: r
+h_consumer: r
+h_consumer: r
+v_consumer: e
+v_consumer: f
+v_consumer: f
+h_consumer: s
+h_consumer: s
+h_consumer: s
+v_consumer: f
+v_consumer: g
+v_consumer: g
+h_consumer: t
+h_consumer: t
+h_consumer: t
+v_consumer: g
+v_consumer: h
+v_consumer: h
+h_consumer: u
+h_consumer: u
+h_consumer: u
+v_consumer: h
+v_consumer: i
+v_consumer: i
+h_consumer: v
+h_consumer: v
+h_consumer: v
+v_consumer: i
+v_consumer: j
+v_consumer: j
+h_consumer: w
+h_consumer: w
+h_consumer: w
+v_consumer: j
+v_consumer: k
+v_consumer: k
+h_consumer: x
+h_consumer: x
+h_consumer: x
+v_consumer: k
+v_consumer: l
+v_consumer: l
+h_consumer: y
+h_consumer: y
+h_consumer: y
+v_consumer: l
+v_consumer: m
+v_consumer: m
+h_consumer: z
+h_consumer: z
+h_consumer: z
+v_consumer: m
--- /dev/null
+input_generator: Write to zeroinput_0: 0.000000\r
+input_generator: Write to matrixA_0_0_0: 1.000000\r
+input_generator: Write to matrixB_0_0_0: 0.000000\r
+input_generator: Write to matrixA_1_0_0: 1.000000\r
+input_generator: Write to matrixB_1_0_0: 0.000000\r
+input_generator: Write to zeroinput_1: 0.000000\r
+input_generator: Write to matrixA_0_0_1: 2.000000\r
+input_generator: Write to matrixB_0_0_1: -1.000000\r
+input_generator: Write to matrixA_1_0_1: 2.000000\r
+input_generator: Write to matrixB_1_0_1: -1.000000\r
+input_generator: Write to zeroinput_2: 0.000000\r
+input_generator: Write to matrixA_0_1_0: 3.000000\r
+input_generator: Write to matrixB_0_1_0: -2.000000\r
+input_generator: Write to matrixA_1_1_0: 3.000000\r
+input_generator: Write to matrixB_1_1_0: -2.000000\r
+input_generator: Write to zeroinput_3: 0.000000\r
+input_generator: Write to matrixA_0_1_1: 4.000000\r
+input_generator: Write to matrixB_0_1_1: -3.000000\r
+input_generator: Write to matrixA_1_1_1: 4.000000\r
+input_generator: Write to matrixB_1_1_1: -3.000000\r
+ addmult_0_0_0: 1.000000 * 0.000000 + 0.000000 = 0.000000\r
+ addmult_0_0_1: 2.000000 * -2.000000 + 0.000000 = -4.000000\r
+ addmult_0_1_0: 3.000000 * 0.000000 + 0.000000 = 0.000000\r
+ addmult_0_1_1: 4.000000 * -2.000000 + 0.000000 = -8.000000\r
+ addmult_1_0_0: 1.000000 * -1.000000 + 0.000000 = -1.000000\r
+ addmult_1_0_1: 2.000000 * -3.000000 + -1.000000 = -7.000000\r
+ addmult_1_1_0: 3.000000 * -1.000000 + 0.000000 = -3.000000\r
+ addmult_1_1_1: 4.000000 * -3.000000 + -3.000000 = -15.000000\r
+output_consumer: matrixC[0][0]: -4.000000\r
+output_consumer: matrixC[0][1]: -7.000000\r
+output_consumer: matrixC[1][0]: -8.000000\r
+output_consumer: matrixC[1][1]: -15.000000\r
--- /dev/null
+input_generator: Write to zeroinput_0: 0.000000\r
+input_generator: Write to matrixA_0_0_0: 1.000000\r
+input_generator: Write to matrixB_0_0_0: 0.000000\r
+input_generator: Write to matrixA_1_0_0: 1.000000\r
+input_generator: Write to matrixB_1_0_0: 0.000000\r
+input_generator: Write to zeroinput_1: 0.000000\r
+input_generator: Write to matrixA_0_0_1: 2.000000\r
+input_generator: Write to matrixB_0_0_1: -1.000000\r
+input_generator: Write to matrixA_1_0_1: 2.000000\r
+input_generator: Write to matrixB_1_0_1: -1.000000\r
+input_generator: Write to zeroinput_2: 0.000000\r
+input_generator: Write to matrixA_0_1_0: 3.000000\r
+input_generator: Write to matrixB_0_1_0: -2.000000\r
+input_generator: Write to matrixA_1_1_0: 3.000000\r
+input_generator: Write to matrixB_1_1_0: -2.000000\r
+input_generator: Write to zeroinput_3: 0.000000\r
+input_generator: Write to matrixA_0_1_1: 4.000000\r
+input_generator: Write to matrixB_0_1_1: -3.000000\r
+input_generator: Write to matrixA_1_1_1: 4.000000\r
+input_generator: Write to matrixB_1_1_1: -3.000000\r
+ addmult_0_0_0: 1.000000 * 0.000000 + 0.000000 = 0.000000\r
+ addmult_0_0_1: 2.000000 * -2.000000 + 0.000000 = -4.000000\r
+ addmult_0_1_0: 3.000000 * 0.000000 + 0.000000 = 0.000000\r
+ addmult_0_1_1: 4.000000 * -2.000000 + 0.000000 = -8.000000\r
+ addmult_1_0_0: 1.000000 * -1.000000 + 0.000000 = -1.000000\r
+ addmult_1_0_1: 2.000000 * -3.000000 + -1.000000 = -7.000000\r
+ addmult_1_1_0: 3.000000 * -1.000000 + 0.000000 = -3.000000\r
+ addmult_1_1_1: 4.000000 * -3.000000 + -3.000000 = -15.000000\r
+output_consumer: matrixC[0][0]: -4.000000\r
+output_consumer: matrixC[0][1]: -7.000000\r
+output_consumer: matrixC[1][0]: -8.000000\r
+output_consumer: matrixC[1][1]: -15.000000\r
--- /dev/null
+ FFT2_0_0: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_1: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_2: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_3: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_4: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_5: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_6: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_7: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_0: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_1: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_1_2: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_3: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_1_4: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_5: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_1_6: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_7: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_2_0: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_2_1: twiddle_factor 0.707107 + j * -0.707107
+ FFT2_2_2: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_2_3: twiddle_factor -0.707107 + j * -0.707107
+ FFT2_2_4: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_2_5: twiddle_factor 0.707107 + j * -0.707107
+ FFT2_2_6: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_2_7: twiddle_factor -0.707107 + j * -0.707107
+ FFT2_3_0: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_3_1: twiddle_factor 0.923880 + j * -0.382683
+ FFT2_3_2: twiddle_factor 0.707107 + j * -0.707107
+ FFT2_3_3: twiddle_factor 0.382683 + j * -0.923880
+ FFT2_3_4: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_3_5: twiddle_factor -0.382684 + j * -0.923880
+ FFT2_3_6: twiddle_factor -0.707107 + j * -0.707107
+ FFT2_3_7: twiddle_factor -0.923880 + j * -0.382683
+input_generator: Write to input_coefficients_0: -7.000000 + j * 6.000000
+input_generator: Write to input_coefficients_1: -6.000000 + j * -6.000000
+input_generator: Write to input_coefficients_2: 1.000000 + j * -1.000000
+input_generator: Write to input_coefficients_3: 1.000000 + j * 2.000000
+input_generator: Write to input_coefficients_4: -7.000000 + j * -2.000000
+input_generator: Write to input_coefficients_5: -8.000000 + j * 0.000000
+input_generator: Write to input_coefficients_6: -8.000000 + j * 1.000000
+input_generator: Write to input_coefficients_7: -8.000000 + j * 1.000000
+input_generator: Write to input_coefficients_8: -2.000000 + j * 8.000000
+input_generator: Write to input_coefficients_9: -4.000000 + j * 0.000000
+input_generator: Write to input_coefficients_10: 1.000000 + j * 6.000000
+input_generator: Write to input_coefficients_11: -1.000000 + j * 3.000000
+input_generator: Write to input_coefficients_12: -2.000000 + j * 3.000000
+input_generator: Write to input_coefficients_13: -3.000000 + j * -2.000000
+input_generator: Write to input_coefficients_14: -4.000000 + j * -8.000000
+input_generator: Write to input_coefficients_15: -3.000000 + j * -5.000000
+output_consumer: coeff[0]: -60.000000 + j * 6.000000
+output_consumer: coeff[1]: 0.616942 + j * -12.269464
+output_consumer: coeff[2]: 8.464464 + j * -18.677670
+output_consumer: coeff[3]: -7.116004 + j * 10.640678
+output_consumer: coeff[4]: -17.000000 + j * 27.000000
+output_consumer: coeff[5]: -9.306217 + j * 18.624950
+output_consumer: coeff[6]: -1.393398 + j * 27.707106
+output_consumer: coeff[7]: -3.112326 + j * -3.457108
+output_consumer: coeff[8]: 4.000000 + j * 20.000000
+output_consumer: coeff[9]: -12.131660 + j * 1.298900
+output_consumer: coeff[10]: 15.535534 + j * 16.677666
+output_consumer: coeff[11]: 4.287576 + j * 3.643592
+output_consumer: coeff[12]: 1.000000 + j * 7.000000
+output_consumer: coeff[13]: -19.179064 + j * 4.345614
+output_consumer: coeff[14]: -22.606600 + j * 26.292894
+output_consumer: coeff[15]: 5.940753 + j * -38.827164
--- /dev/null
+ FFT2_0_0: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_1: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_2: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_3: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_4: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_5: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_6: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_0_7: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_0: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_1: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_1_2: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_3: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_1_4: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_5: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_1_6: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_1_7: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_2_0: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_2_1: twiddle_factor 0.707107 + j * -0.707107
+ FFT2_2_2: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_2_3: twiddle_factor -0.707107 + j * -0.707107
+ FFT2_2_4: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_2_5: twiddle_factor 0.707107 + j * -0.707107
+ FFT2_2_6: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_2_7: twiddle_factor -0.707107 + j * -0.707107
+ FFT2_3_0: twiddle_factor 1.000000 + j * -0.000000
+ FFT2_3_1: twiddle_factor 0.923880 + j * -0.382683
+ FFT2_3_2: twiddle_factor 0.707107 + j * -0.707107
+ FFT2_3_3: twiddle_factor 0.382683 + j * -0.923880
+ FFT2_3_4: twiddle_factor -0.000000 + j * -1.000000
+ FFT2_3_5: twiddle_factor -0.382683 + j * -0.923880
+ FFT2_3_6: twiddle_factor -0.707107 + j * -0.707107
+ FFT2_3_7: twiddle_factor -0.923880 + j * -0.382683
+input_generator: Write to input_coefficients_0: -9.000000 + j * 4.000000
+input_generator: Write to input_coefficients_1: -2.000000 + j * 0.000000
+input_generator: Write to input_coefficients_2: -3.000000 + j * 0.000000
+input_generator: Write to input_coefficients_3: 8.000000 + j * 3.000000
+input_generator: Write to input_coefficients_4: 6.000000 + j * 0.000000
+input_generator: Write to input_coefficients_5: -7.000000 + j * -9.000000
+input_generator: Write to input_coefficients_6: -5.000000 + j * 2.000000
+input_generator: Write to input_coefficients_7: 1.000000 + j * 2.000000
+input_generator: Write to input_coefficients_8: 8.000000 + j * -4.000000
+input_generator: Write to input_coefficients_9: -6.000000 + j * -4.000000
+input_generator: Write to input_coefficients_10: 9.000000 + j * -2.000000
+input_generator: Write to input_coefficients_11: -8.000000 + j * -4.000000
+input_generator: Write to input_coefficients_12: -3.000000 + j * 1.000000
+input_generator: Write to input_coefficients_13: -9.000000 + j * 7.000000
+input_generator: Write to input_coefficients_14: -9.000000 + j * -9.000000
+input_generator: Write to input_coefficients_15: -7.000000 + j * 7.000000
+output_consumer: coeff[0]: -36.000000 + j * -6.000000
+output_consumer: coeff[1]: -27.156870 + j * -5.812504
+output_consumer: coeff[2]: -6.071069 + j * -25.242640
+output_consumer: coeff[3]: -7.438680 + j * 7.017483
+output_consumer: coeff[4]: -3.999999 + j * 28.000000
+output_consumer: coeff[5]: 1.106642 + j * 13.313931
+output_consumer: coeff[6]: -18.899494 + j * 3.443651
+output_consumer: coeff[7]: -46.865753 + j * -33.359482
+output_consumer: coeff[8]: 24.000000 + j * -10.000000
+output_consumer: coeff[9]: -13.085772 + j * 2.398290
+output_consumer: coeff[10]: 8.071067 + j * -16.757360
+output_consumer: coeff[11]: 16.450871 + j * 51.024147
+output_consumer: coeff[12]: 24.000000 + j * -8.000000
+output_consumer: coeff[13]: -32.863998 + j * -13.899717
+output_consumer: coeff[14]: 0.899496 + j * 34.556351
+output_consumer: coeff[15]: -26.146439 + j * 43.317848
--- /dev/null
+producer: samples = { -7.0, +6.0, -6.0, -6.0, +1.0, -1.0, +1.0, +2.0, -7.0, -2.0 }
+producer: Write sample[00]: -7.0000
+producer: Write sample[01]: +6.0000
+producer: Write sample[02]: -6.0000
+consumer: Read sample[00]: -7.0000
+producer: Write sample[03]: -6.0000
+consumer: Read sample[01]: +2.5000
+producer: Write sample[04]: +1.0000
+consumer: Read sample[02]: -4.7500
+producer: Write sample[05]: -1.0000
+consumer: Read sample[03]: -8.3750
+producer: Write sample[06]: +1.0000
+consumer: Read sample[04]: -3.1875
+producer: Write sample[07]: +2.0000
+consumer: Read sample[05]: -2.5938
+producer: Write sample[08]: -7.0000
+consumer: Read sample[06]: -0.2969
+producer: Write sample[09]: -2.0000
+consumer: Read sample[07]: +1.8516
+consumer: Read sample[08]: -6.0742
+consumer: Read sample[09]: -5.0371
--- /dev/null
+producer: samples = { -9.0, +4.0, -2.0, +0.0, -3.0, +0.0, +8.0, +3.0, +6.0, +0.0 }
+producer: Write sample[00]: -9.0000
+producer: Write sample[01]: +4.0000
+producer: Write sample[02]: -2.0000
+consumer: Read sample[00]: -9.0000
+producer: Write sample[03]: +0.0000
+consumer: Read sample[01]: -0.5000
+producer: Write sample[04]: -3.0000
+consumer: Read sample[02]: -2.2500
+producer: Write sample[05]: +0.0000
+consumer: Read sample[03]: -1.1250
+producer: Write sample[06]: +8.0000
+consumer: Read sample[04]: -3.5625
+producer: Write sample[07]: +3.0000
+consumer: Read sample[05]: -1.7812
+producer: Write sample[08]: +6.0000
+consumer: Read sample[06]: +7.1094
+producer: Write sample[09]: +0.0000
+consumer: Read sample[07]: +6.5547
+consumer: Read sample[08]: +9.2773
+consumer: Read sample[09]: +4.6387
--- /dev/null
+init producer.
+init consumer.
+init filter_0: filter coefficient = -0.9
+init filter_1: filter coefficient = -0.6
+init filter_2: filter coefficient = -0.1
+producer: samples = { -7.0, +6.0, -6.0, -6.0, +1.0 }
+producer: Write sample[00]: -7.0000
+producer: Write sample[01]: +6.0000
+filter_0: inA: -7.0000, inB: 0.0000, outA = outB: -7.0000
+filter_1: inA: -7.0000, inB: 0.0000, outA: -7.0000, outB: 4.2000
+filter_2: inA: -7.0000, inB: 0.0000, outA: -7.0000, outB: 0.7000
+producer: Write sample[02]: -6.0000
+consumer: Read sample[00]: -7.0000
+filter_0: inA: 6.0000, inB: 4.2000, outA = outB: 10.2000
+filter_1: inA: 10.2000, inB: 0.7000, outA: 10.2000, outB: -5.4200
+filter_2: inA: 10.2000, inB: 0.0000, outA: 10.2000, outB: -1.0200
+producer: Write sample[03]: -6.0000
+consumer: Read sample[01]: +10.2000
+filter_0: inA: -6.0000, inB: -5.4200, outA = outB: -11.4200
+filter_1: inA: -11.4200, inB: -1.0200, outA: -11.4200, outB: 5.8320
+filter_2: inA: -11.4200, inB: 0.0000, outA: -11.4200, outB: 1.1420
+producer: Write sample[04]: +1.0000
+consumer: Read sample[02]: -11.4200
+filter_0: inA: -6.0000, inB: 5.8320, outA = outB: -0.1680
+filter_1: inA: -0.1680, inB: 1.1420, outA: -0.1680, outB: 1.2428
+filter_2: inA: -0.1680, inB: 0.0000, outA: -0.1680, outB: 0.0168
+consumer: Read sample[03]: -0.1680
+filter_0: inA: 1.0000, inB: 1.2428, outA = outB: 2.2428
+filter_1: inA: 2.2428, inB: 0.0168, outA: 2.2428, outB: -1.3289
+filter_2: inA: 2.2428, inB: 0.0000, outA: 2.2428, outB: -0.2243
+consumer: Read sample[04]: +2.2428
--- /dev/null
+init producer.
+init consumer.
+init filter_0: filter coefficient = -1.0
+init filter_1: filter coefficient = +0.1
+init filter_2: filter coefficient = -0.1
+producer: samples = { -9.0, +4.0, -2.0, +0.0, -3.0 }
+producer: Write sample[00]: -9.0000
+producer: Write sample[01]: +4.0000
+filter_0: inA: -9.0000, inB: 0.0000, outA = outB: -9.0000
+filter_1: inA: -9.0000, inB: 0.0000, outA: -9.0000, outB: -0.9000
+filter_2: inA: -9.0000, inB: 0.0000, outA: -9.0000, outB: 0.9000
+producer: Write sample[02]: -2.0000
+consumer: Read sample[00]: -9.0000
+filter_0: inA: 4.0000, inB: -0.9000, outA = outB: 3.1000
+filter_1: inA: 3.1000, inB: 0.9000, outA: 3.1000, outB: 1.2100
+filter_2: inA: 3.1000, inB: 0.0000, outA: 3.1000, outB: -0.3100
+producer: Write sample[03]: +0.0000
+consumer: Read sample[01]: +3.1000
+filter_0: inA: -2.0000, inB: 1.2100, outA = outB: -0.7900
+filter_1: inA: -0.7900, inB: -0.3100, outA: -0.7900, outB: -0.3890
+filter_2: inA: -0.7900, inB: 0.0000, outA: -0.7900, outB: 0.0790
+producer: Write sample[04]: -3.0000
+consumer: Read sample[02]: -0.7900
+filter_0: inA: 0.0000, inB: -0.3890, outA = outB: -0.3890
+filter_1: inA: -0.3890, inB: 0.0790, outA: -0.3890, outB: 0.0401
+filter_2: inA: -0.3890, inB: 0.0000, outA: -0.3890, outB: 0.0389
+consumer: Read sample[03]: -0.3890
+filter_0: inA: -3.0000, inB: 0.0401, outA = outB: -2.9599
+filter_1: inA: -2.9599, inB: 0.0389, outA: -2.9599, outB: -0.2571
+filter_2: inA: -2.9599, inB: 0.0000, outA: -2.9599, outB: 0.2960
+consumer: Read sample[04]: -2.9599
--- /dev/null
+task_0: 0
+task_1: 0
+task_2: 0
+task_0: 1
+task_1: 1
+task_2: 1
+task_0: 2
+task_1: 2
+task_2: 2
+task_0: 3
+task_1: 3
+task_2: 3
+task_0: 4
+task_1: 4
+task_2: 4
+task_0: 5
+task_1: 5
+task_2: 5
+task_0: 6
+task_1: 6
+task_2: 6
+task_0: 7
+task_1: 7
+task_2: 7
+task_0: 8
+task_1: 8
+task_2: 8
+task_0: 9
+task_1: 9
+task_2: 9
--- /dev/null
+task_0: 0
+task_1: 0
+task_2: 0
+task_0: 1
+task_1: 1
+task_2: 1
+task_0: 2
+task_1: 2
+task_2: 2
+task_0: 3
+task_1: 3
+task_2: 3
+task_0: 4
+task_1: 4
+task_2: 4
+task_0: 5
+task_1: 5
+task_2: 5
+task_0: 6
+task_1: 6
+task_2: 6
+task_0: 7
+task_1: 7
+task_2: 7
+task_0: 8
+task_1: 8
+task_2: 8
+task_0: 9
+task_1: 9
+task_2: 9
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project name="dol" default="all" basedir=".">
+
+ <description>
+ Ant build file to run tests.
+ </description>
+
+ <!-- directory paths -->
+ <property name="lib.dir" location="./../../../jars"/>
+ <property name="bin.dir" location="./../../../bin"/>
+ <property name="jars" value=".:./..:${lib.dir}/dol.jar:${lib.dir}/xercesImpl.jar:${lib.dir}/jdom.jar:${bin.dir}/dol.jar:${bin.dir}/xercesImpl.jar:${bin.dir}/jdom.jar"/>
+ <property name="example.dir" location="./../../../examples"/>
+ <property name="test.dir" location="./../../../test"/>
+
+ <property name="generator" value="HdS"/> <!-- HdS, protothread, systemC, PaF -->
+
+ <target name="all" depends="xml, checkexamples"/>
+
+ <!-- check validity of XML documents -->
+ <target name="xml">
+ <echo message="Check XML documents."/>
+ <java classname="test.test.TreeValidator"
+ dir="."
+ fork="true"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="${example.dir}/schema
+ ${example.dir}/exampleproducerconsumer
+ ${example.dir}/example1
+ ${example.dir}/example2
+ ${example.dir}/example3
+ ${example.dir}/example4
+ ${example.dir}/example5
+ ${example.dir}/example6
+ ${example.dir}/example7
+ ${example.dir}/examplesingleprocess
+ ${example.dir}/arch"/>
+ </java>
+ </target>
+
+ <!-- compile and run examples and check agains reference output -->
+ <macrodef name="runandcheck">
+ <attribute name="number"/>
+ <sequential>
+ <ant antfile="runexample.xml"
+ target="runexample"
+ inheritAll="false">
+ <property name="number" value="@{number}"/>
+ <property name="generator" value="${generator}"/>
+ </ant>
+
+ <copy file="example@{number}/${generator}/src/log.txt"
+ tofile="test/example@{number}log.txt"
+ overwrite="true">
+ </copy>
+
+ <copy file="${test.dir}/reference/example@{number}_${os.name}.txt"
+ tofile="test/example@{number}ref.txt"
+ overwrite="true">
+ </copy>
+
+ <java classname="test.util.Diff"
+ dir="."
+ fork="true"
+ failonerror="true">
+ <classpath path="${jars}"/>
+ <arg line="test/example@{number}ref.txt test/example@{number}log.txt "/>
+ </java>
+
+ <java classname="dol.main.Main"
+ dir="."
+ fork="true"
+ classpath="${jars}"
+ failonerror="true">
+ <arg line=" -T profile.txt -P example@{number}/example@{number}_flattened.xml -G example@{number}/example@{number}_flattened_annotated.xml"/>
+ </java>
+
+ <echo message="Successfully tested example @{number}."/>
+ </sequential>
+ </macrodef>
+
+ <!-- check all examples -->
+ <target name="checkexamples">
+ <echo message="Check examples."/>
+ <mkdir dir="test"/>
+ <runandcheck number="1"/>
+ <runandcheck number="2"/>
+ <runandcheck number="4"/>
+ <runandcheck number="6"/>
+ <runandcheck number="7"/>
+ <runandcheck number="singleprocess"/>
+ <runandcheck number="3"/>
+ </target>
+
+</project>
--- /dev/null
+package test.test;
+
+import java.io.File;
+
+import test.util.XMLValidator;
+
+/**
+ * Class to check well-formedness and validity of XML documents.
+ */
+public class TreeValidator {
+
+ /**
+ * Check the well-formedness and validity of XML files.
+ *
+ * @param args Specifies the XML file to be checked or the
+ * directory (including subdirectories) where XML
+ * and XSD files are checked. Multiple files or
+ * directories can be specified.
+ */
+ public static void main(String args[]) throws Exception {
+ System.out.println("Run TreeValidator.");
+ if (args.length == 0)
+ browseDirectoryTree("./");
+ else {
+ for (int k = 0; k < args.length; k++)
+ browseDirectoryTree(args[k]);
+ }
+ System.out.println("Finished.");
+ }
+
+ /**
+ * Method which defines what is done for each file found in the
+ * directory tree: When the file is an XML or XSD file, it is
+ * validated using
+ * {@link test.util.XMLValidator#isValid(java.lang.String)}.
+ *
+ * @param filename file to process
+ */
+ protected static void processFile(String filename) throws Exception {
+ if (filename.endsWith("xml") || filename.endsWith("xsd")) {
+ System.out.println("Checking " + filename + "...");
+ if (!XMLValidator.isValid(filename))
+ throw new Exception("File not valid.");
+ }
+ }
+
+ /**
+ * Iterate through the given directory tree. For each file found in
+ * the file, the method {@link #processFile(java.lang.String)} is
+ * called.
+ *
+ * @param path the path of the directory to be browsed
+ */
+ protected static void browseDirectoryTree(String path) throws Exception {
+ File file = new File(path);
+
+ if (!file.exists()) return;
+ if (!file.isDirectory()) return;
+
+ String filepath = file.getPath();
+ String filename = file.getName();
+
+ //loop through files in directory
+ String[] files = file.list();
+
+ for (int k = 0; k < files.length; k++) {
+ File newfile = new File(file.getPath(), files[k]);
+ if (newfile.isFile())
+ processFile(path + System.getProperty("file.separator")
+ + files[k]);
+ else if (newfile.isDirectory()) {
+ browseDirectoryTree(file.getPath()
+ + System.getProperty("file.separator")
+ + files[k]);
+ }
+ }
+ }
+}
--- /dev/null
+package test.util;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.FileReader;\r
+\r
+/**\r
+ * Class to diff two files\r
+ */\r
+public class Diff {\r
+\r
+ /**\r
+ * Main.\r
+ *\r
+ * @param args names of the two files to compare\r
+ */\r
+ public static void main(String[] args) throws Exception {\r
+ if (args.length != 2) {\r
+ //System.out.println("Usage: java Diff file1 file2");\r
+ throw new Exception("Usage: java Diff file1 file2");\r
+ }\r
+\r
+ try {\r
+ BufferedReader fileOneReader = new BufferedReader(new FileReader(args[0]));\r
+ BufferedReader fileTwoReader = new BufferedReader(new FileReader(args[1]));\r
+\r
+ String lineOne, lineTwo;\r
+ while ((lineOne = fileOneReader.readLine()) != null) {\r
+ lineTwo = fileTwoReader.readLine();\r
+ if (lineTwo == null)\r
+ throw new Exception("Files are not equal: "\r
+ + args[1] + " is shorter.");\r
+ else if (!lineOne.equals(lineTwo))\r
+ throw new Exception("Files do not match.");\r
+ }\r
+\r
+ if ((lineTwo = fileTwoReader.readLine()) != null)\r
+ throw new Exception("Files are not equal: "\r
+ + args[0] + " is shorter.");\r
+ }\r
+ catch (Exception e) {\r
+ throw e;\r
+ }\r
+\r
+ //System.out.println("Files are equal.");\r
+ }\r
+}\r
--- /dev/null
+package test.util;
+
+import java.util.ResourceBundle;
+import java.io.IOException;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+/**
+ * Class to check well-formedness and validity of XML documents.
+ */
+public class XMLValidator {
+
+ /**
+ * Check the well-formedness and validity of an XML document.
+ * The file is checked against the schema which is referenced from
+ * within the file. When the document is an XML schema, it is checked
+ * against <a href="http://www.w3.org/2001/XMLSchema.xsd"
+ * target="_blank">http://www.w3.org/2001/XMLSchema.xsd</a>.
+ *
+ * @param filename filename of the file to be checked
+ */
+ public static boolean isValid(String filename) {
+ ResourceBundle resourceBundle = ResourceBundle.getBundle("test");
+
+ SAXBuilder builder = new SAXBuilder(true);
+ builder.setFeature("http://xml.org/sax/features/validation",
+ true);
+ builder.setFeature("http://apache.org/xml/features/validation/"
+ + "schema", true);
+ builder.setFeature("http://apache.org/xml/features/validation/"
+ + "schema-full-checking", true);
+ builder.setProperty("http://apache.org/xml/properties/schema/"
+ + "external-schemaLocation",
+ "http://www.w3.org/2001/XMLSchema "
+ + "http://www.w3.org/2001/XMLSchema.xsd "
+ + resourceBundle.getString("LOCAL_SCHEMAS"));
+
+ try {
+ builder.build(filename);
+ }
+ catch (JDOMException e) {
+ System.out.println("Found an error in " + filename + ".");
+ System.out.println(e.getMessage());
+ System.out.println("");
+ return false;
+ }
+ catch (IOException e) {
+ System.out.println("Found an error in " + filename + ".");
+ System.out.println(e.getMessage());
+ System.out.println("");
+ return false;
+ }
+
+ return true;
+ }
+}
--- /dev/null
+#local schemas for validation of XML files
+LOCAL_SCHEMAS = \
+ http://www.tik.ee.ethz.ch/~shapes/schema/PROCESSNETWORK \
+ file:///@schema_path@/processnetwork.xsd \
+ http://www.tik.ee.ethz.ch/~shapes/schema/ARCHITECTURE \
+ file:///@schema_path@/architecture.xsd \
+ http://www.tik.ee.ethz.ch/~shapes/schema/MAPPING \
+ file:///@schema_path@/mapping.xsd
+