kshalle@26: /* kshalle@26: * Copyright 2011 OpenSourceResearchInstitute.org kshalle@26: * Licensed under GNU General Public License version 2 kshalle@26: * kshalle@26: * Author: seanhalle@yahoo.com kshalle@26: * kshalle@26: */ kshalle@26: #include "HWSim__PingPong__HWDef/HWSim__PingPong__HWDef.h" kshalle@26: kshalle@26: /* is an expr resolves to an actual commPath struct instance kshalle@26: */ kshalle@26: #define setCommPathValuesTo( commPath, fromElIdx, outPort, toElIdx, inPort)\ kshalle@26: do{\ kshalle@26: commPath->idxOfFromElem = fromElIdx; \ kshalle@26: commPath->idxOfFromOutPort = outPort; \ kshalle@26: commPath->idxOfToElem = toElIdx; \ kshalle@26: commPath->idxOfToInPort = inPort; \ kshalle@26: }while(0); //macro magic for namespace kshalle@26: kshalle@26: kshalle@26: kshalle@26: HWSimActivityType* createPingPongActivityType (); kshalle@26: kshalle@26: HWSimElem* createAPingPongElem (HWSimNetlist *netlist); kshalle@26: kshalle@26: /*This file constructs the netlist for the Hello World circuit kshalle@26: * kshalle@26: *It has two elements, each with one input port and one output port, and kshalle@26: * a single activity-type. kshalle@26: * kshalle@26: *The elements are cross-coupled, so output port of one connects to input kshalle@26: * port of the other. The input port has a single trigger, which fires kshalle@26: * the one activity-type. kshalle@26: * kshalle@26: *The activity does nothing, except send a NULL message on the output port. kshalle@26: *The activity-sim-time and communication-sim-time are both constants. kshalle@26: * kshalle@26: *Note that elements are generic. They are specialized by declaring kshalle@26: * inports and outports, and by registering triggers that fire particular kshalle@26: * activity-types. kshalle@26: */ kshalle@26: HWSimNetlist *createPingPongNetlist() kshalle@26: { HWSimNetlist *netlist; kshalle@26: HWSimCommPath **commPaths; kshalle@26: HWSimElem **elems; kshalle@26: int32 numElems; kshalle@26: int32 numCommPaths; kshalle@26: kshalle@26: netlist = malloc( sizeof(HWSimNetlist) ); kshalle@26: numElems= 2; kshalle@26: elems = malloc( numElems * sizeof(HWSimElem *) ); kshalle@26: netlist->numElems = numElems; kshalle@26: netlist->elems = elems; kshalle@26: netlist->numActivityTypes = 1; kshalle@26: netlist->activityTypes = malloc(netlist->numActivityTypes*sizeof(HWSimActivityType*)); kshalle@26: kshalle@26: netlist->activityTypes[PING_PONG_ACTIVITY] = createPingPongActivityType(); kshalle@26: kshalle@26: elems[0] = createAPingPongElem( netlist ); //use activity types from netlist kshalle@26: elems[1] = createAPingPongElem( netlist ); kshalle@26: kshalle@26: //make reset trigger an action on one of the elements kshalle@26: elems[1]->inPorts[-1].triggeredActivityType = kshalle@26: netlist->activityTypes[PING_PONG_ACTIVITY]; kshalle@26: kshalle@26: /*OutPorts and InPorts may have many commPaths attached. kshalle@26: * but an inPort only kshalle@26: * has one kind of activity that all incoming communications trigger. That kshalle@26: * activity can be zero time and then switch on the type of message then kshalle@26: * end with a continuation, where the continuation activity is chosen by the kshalle@26: * switch. kshalle@26: *So, a commPath only connects an out port to an in port kshalle@26: *The format is: sending elem-index, out-port, dest elem-index, in-port kshalle@26: */ kshalle@26: numCommPaths = 2; kshalle@26: commPaths = malloc( numCommPaths * sizeof(HWSimCommPath *) ); kshalle@26: netlist->numCommPaths= numCommPaths; kshalle@26: netlist->commPaths= commPaths; kshalle@26: //elem 0, out-port 0 to elem 1, in-port 0 kshalle@26: commPaths[0]= malloc(sizeof(HWSimCommPath)); kshalle@26: setCommPathValuesTo(commPaths[0],0,0,1,0); kshalle@26: commPaths[0]->hasFixedTiming = TRUE; kshalle@26: commPaths[0]->fixedFlightTime = 10; //all time is stated in (integer) units kshalle@26: kshalle@26: //elem 1, out-port 0 to elem 0, in-port 0 kshalle@26: commPaths[1]= malloc(sizeof(HWSimCommPath)); kshalle@26: setCommPathValuesTo(commPaths[1], 1,0,0,0); kshalle@26: commPaths[1]->hasFixedTiming = TRUE; kshalle@26: commPaths[1]->fixedFlightTime = 10; //all time is stated in (integer) units kshalle@26: kshalle@26: //TODO: decide how to do bidirectional commPaths, like connection to a bus kshalle@26: // thinking make it two separate commPaths with guard between in-port and out-port kshalle@26: kshalle@26: return netlist; kshalle@26: } kshalle@26: kshalle@26: kshalle@26: /* kshalle@26: */ kshalle@26: void kshalle@26: freePingPongNetlist (HWSimNetlist *netlist) kshalle@26: { int i; kshalle@26: kshalle@26: for( i = 0; i < netlist->numCommPaths; i++ ) kshalle@26: { free(netlist->commPaths[i]); kshalle@26: } kshalle@26: free(netlist->commPaths); kshalle@26: for( i= 0; i < netlist->numElems; i++ ) kshalle@26: { HWSim_ext__free_inPortsArray( netlist->elems[i]->inPorts ); kshalle@26: free(netlist->elems[i]->outPorts); kshalle@26: free(netlist->elems[i]); kshalle@26: } kshalle@26: kshalle@26: free(netlist->activityTypes); kshalle@26: free(netlist->elems); kshalle@26: free(netlist); kshalle@26: } kshalle@26: kshalle@26: /*This creates a simulation element. A simulation element is of the type kshalle@26: * HWSimElem. The HWSimElem data structure contains information about kshalle@26: * the input ports and output ports of the element. In particular, when kshalle@26: * a communication arrives on an input port, that triggers activity inside kshalle@26: * the element. It is here that the function is registerd, which implements kshalle@26: * the behavior of that activity. kshalle@26: *Triggered activities is the heart of HWSim. It is inside these functions kshalle@26: * that application defined behavior takes place. kshalle@26: */ kshalle@26: HWSimElem * kshalle@26: createAPingPongElem( HWSimNetlist *netlist ) kshalle@26: { HWSimElem *elem; kshalle@26: elem = malloc( sizeof(HWSimElem) ); kshalle@26: elem->numInPorts = 1; kshalle@26: elem->numOutPorts = 1; kshalle@26: elem->inPorts = HWSim_ext__make_inPortsArray( elem->numInPorts ); kshalle@26: elem->inPorts[-1].triggeredActivityType = IDLE_SPAN; //reset port kshalle@26: //point the trigger at an activity that is already in the netlist. kshalle@26: // The function below creates one of such activities. kshalle@26: //The netlist creation function first creates the activities, then kshalle@26: // it calls this function, which grabs activities from the netlist kshalle@26: elem->inPorts[0].triggeredActivityType = netlist->activityTypes[PING_PONG_ACTIVITY]; kshalle@26: return elem; kshalle@26: } kshalle@26: kshalle@26: /*Define a type of activity that is possible. The netlist creator kshalle@26: * first calls all of this kind of function, and fills the netlist kshalle@26: * with these data structures that implement activities. kshalle@26: *Then, the creator calls functions that create individual elements. kshalle@26: * Those element-creation functions grab the activity structures out kshalle@26: * of the netlist. kshalle@26: */ kshalle@26: HWSimActivityType * kshalle@26: createPingPongActivityType( ) kshalle@26: { HWSimActivityType *pingPongActivityType; kshalle@26: pingPongActivityType = malloc( sizeof(HWSimActivityType) ); kshalle@26: kshalle@26: //For execution speed, some special cases exist, such as activities kshalle@26: // that have no behavior, or ones that have a fixed time to complete kshalle@26: pingPongActivityType->hasBehavior = TRUE; kshalle@26: pingPongActivityType->hasTiming = TRUE; kshalle@26: pingPongActivityType->timingIsFixed = TRUE; kshalle@26: pingPongActivityType->fixedTime = 10; kshalle@26: pingPongActivityType->behaviorFn = &pingPongElem_PingActivity_behavior; kshalle@26: return pingPongActivityType; kshalle@26: } kshalle@26: