/* save the instance resource into the stream */ static __bool _save_inst_res_proc(ITreeNode * nd, __bool firstVisit, f8_uint _s) { IBlk * blk; ICBlk * cblk; struct cblk_link_t * lk; struct blk_pin_t * p; struct cblk_pin_t * cp; IF8Stream * s; s = (IF8Stream*)_s; blk = __dcast__(ITreeNode, IBlk, nd); save_res_stream(&blk->uuid, s); if(blk->h.magic == CBLK_MAGIC){ cblk = __dcast__(IBlk, ICBlk, (blk)); lk = ICBlk_first_link(cblk); while(lk){ save_res_stream(&lk->uuid, s); lk = ICBlk_next_link(lk); } p = __vcall__(blk, first_pin, (blk)); while(p){ cp = CONTAINING_RECORD(p, struct cblk_pin_t, p); save_res_stream(&cp->uuid, s); p = __vcall__(blk, next_pin, (p)); } }
FBD_API struct cblk_link_t * ICBlk_next_connection(struct blk_pin_t *p, struct cblk_link_t * lk) { IBlk *b; ICBlk *cb; struct blk_pin_t *rp; b = parent_blk(p->blk); assert(b); assert(b->h.magic == CBLK_MAGIC); cb = __dcast__(IBlk, ICBlk, b); rp = IBlk_real_pin(p); if(rp->_class != PIN_CLASS_DO && rp->_class != PIN_CLASS_EO) { return 0; } // search in the link array lk = _next_link(lk); while(lk) { if(lk->s.pin == p) { return lk; } lk = _next_link(lk); } return 0; }
/* return a pin's first logical peer, i.e., pin within the same level in the block treelist. */ FBD_API struct cblk_link_t * ICBlk_first_connection(struct blk_pin_t *p) { IBlk *b; ICBlk *cb; int i; struct cblk_link_t * lk; b = parent_blk(p->blk); if(!b) { // this is the top-level pin return 0; } assert(b); assert(b->h.magic == CBLK_MAGIC); cb = __dcast__(IBlk, ICBlk, b); // search in the link array for(i=0, lk=_first_link(cb); i<b->h.u2.n_links; i++, lk=_next_link(lk)) { if(lk->s.pin == p) { return lk; } if(lk->t.pin == p) { return lk; } } return 0; }
static int ICommPeer_write(IPeer * _this, const void * buf, int len) { ICommPeer * __this; __this = __dcast__(IPeer, ICommPeer, _this); if(__this->hTty == ERROR){ return F8_INVALID_OPERATION; } return write(__this->hTty, (char*)buf, len); }
static __bool _alloc_var_proc(ITreeNode * nd, __bool firstVisit, __uint context) { IBlk * b; ICBlk * cb; struct blk_var_t *v, var; int len, i; CRegRequirementList * req; req = (CRegRequirementList*)context; b = __dcast__(ITreeNode, IBlk, nd); if(b->h.magic != CBLK_MAGIC){ return __true; } // // // now unpack the variable definitions // // cb = __dcast__(IBlk, ICBlk, b); v = (struct blk_var_t*)get_res_buf(&b->h.uuid, &len, "variables"); if(!v){ return __true; } if(len % sizeof(struct blk_var_t)){ req->m_errcode = F8_INVALID_DATA; return __false; } len /= sizeof(struct blk_var_t); for(i=0; i<len; i++, v++){ var = *v; var.blk = b; var.comment = get_res_buf_v(&b->h.uuid, 0, "!v%d!comment", i); var.addr.section = MEM_SECTION_INVALID; create_f8_uuid(&var.uuid); if(!req->Alloc(&var)){ return __false; } } return __true; }
static __bool ICBlk_save(IBlk * _this, IF8Stream * s) { IBlk * sb; struct cblk_link_t * l; struct cblk_pin_t * p; union blk_pindef_t pd; ICBlk * cblk; cblk = __dcast__(IBlk, ICBlk, _this); // write header __vcall__(s, put, (s, &_this->h, sizeof(_this->h))); // write guid __vcall__(s, put, (s, &_this->uuid, sizeof(f8_uuid))); // write sub-blocks sb = first_subblk(_this); while(sb) { if(!__vcall__(sb, save, (sb, s))) { return __false; } sb = next_blk(sb); } // write link-defs l = _first_link(cblk); while(l) { __vcall__(s, put, (s, &l->uuid, sizeof(l->uuid))); pd.id.bid = IBlk_id_by_blk(l->s.pin->blk); pd.id.pid = __vcall__(l->s.pin->blk, id_by_pin, (l->s.pin)); __vcall__(s, put, (s, &pd, sizeof(pd))); pd.id.bid = IBlk_id_by_blk(l->t.pin->blk); pd.id.pid = __vcall__(l->t.pin->blk, id_by_pin, (l->t.pin)); __vcall__(s, put, (s, &pd, sizeof(pd))); l = _next_link(l); } // write pins p = _first_pin(cblk); while(p) { __vcall__(s, put, (s, &p->uuid, sizeof(p->uuid))); pd.id.bid = IBlk_id_by_blk(p->p.u1.x.id.llink->blk); pd.id.pid = __vcall__(p->p.u1.x.id.llink->blk, id_by_pin, (p->p.u1.x.id.llink)); __vcall__(s, put, (s, &pd, sizeof(pd))); p = _next_pin(cblk, p); } return __true; }
static struct blk_pin_t * ICBlk_first_pin(IBlk * _this) { ICBlk * me; struct cblk_pin_t * pp; me = __dcast__(IBlk, ICBlk, _this); assert(_this->h.magic == CBLK_MAGIC); pp = _first_pin(me); if(pp) { return &pp->p; } return 0; }
static struct blk_pin_t * ICBlk_next_pin(struct blk_pin_t * p) { ICBlk * me; struct cblk_pin_t * pp; assert(p->blk->h.magic == CBLK_MAGIC); me = __dcast__(IBlk, ICBlk, p->blk); pp = SAFE_CONTAINING_RECORD(p, struct cblk_pin_t, p); pp = _next_pin(me, pp); if(pp) { return &pp->p; } return 0; }
FBD_API struct cblk_pin_t * ICBlk_add_pin(f8_uuid * id, struct blk_pin_t * p) { ICBlk * a; IBlk * b; struct cblk_pin_t * t; b = parent_blk(p->blk); if(!b) { return 0; } assert(b->h.magic== CBLK_MAGIC); a = __dcast__(IBlk, ICBlk, b); // re-export not allowed if(p->ulink) { return 0; } // ok, go on t = (struct cblk_pin_t *)mm_alloc( g_hBlkHeap, sizeof(struct cblk_pin_t), 0 ); if( !t ) { return 0; } memset(t, 0, sizeof(struct cblk_pin_t)); t->uuid = *id; // fake a pin structure t->p._class = PIN_CLASS_EXP; t->p.blk = b; t->p.type = 0; t->p.flags = 0; t->p.ulink = 0; t->p.u1.x.id.llink = p; t->p.u1.x.real_pin = IBlk_real_pin(p); t->p.dp = p->dp; p->ulink = &t->p; RtkInsertTailList(&a->pins, &t->sibling); b->h.n_pins++; return t; }
static struct blk_pin_t * ICBlk_pin_by_id(IBlk * blk, __u16 id) { ICBlk * cb; struct cblk_pin_t * p; if(id >= blk->h.n_pins) { return 0; } cb = __dcast__(IBlk, ICBlk, blk); p = _first_pin(cb); while(p && id) { p = _next_pin(cb, p); id--; } return &p->p; }
/* ICBlk::link(p1, p2) allocate data structures to hold this link information, and link the corresponding pin structure */ FBD_API struct cblk_link_t * ICBlk_link(f8_uuid * id, struct blk_pin_t * s, struct blk_pin_t * t) { ICBlk *a; IBlk *b; struct cblk_link_t * lk; if(!IBlk_linkable(s, t)) { return 0; } b = parent_blk(s->blk); a = __dcast__(IBlk, ICBlk, b); if( !IBlk_connect(s, t)) { return 0; } if( !IBlk_is_output(s)) { struct blk_pin_t *tmp; tmp = s; s = t; t = tmp; } // create a new the link object lk = (struct cblk_link_t *)mm_alloc( g_hBlkHeap, sizeof(struct cblk_link_t), 0 ); if(!lk) { IBlk_disconnect(t); return 0; } memset(lk, 0, sizeof(struct cblk_link_t)); lk->blk = a; lk->uuid = *id; lk->s.pin = s; lk->t.pin = t; RtkInsertTailList(&a->links, &lk->sibling); b->h.u2.n_links++; return lk; }
static __u16 ICBlk_id_by_pin(struct blk_pin_t * pin) { int i; ICBlk * cblk; PRTK_LIST_ENTRY le; struct cblk_pin_t * cp; cblk = __dcast__(IBlk, ICBlk, pin->blk); le = cblk->pins.Flink; i = 0; cp = SAFE_CONTAINING_RECORD(pin, struct cblk_pin_t, p); while(le != &cblk->links) { if(le == &cp->sibling) { return i; } le = le->Flink; i++; } return -1; }
LOCAL int IUdpPeer_write(IPeer * _this, const void * buf, int len) { IUdpPeer * __this = __dcast__(IPeer, IUdpPeer, _this); if(__this->vbus){ #if defined(HSP_DEBUG) static int lastCmd; static int lastCount; struct peer_cmd_t * tp; tp = (struct peer_cmd_t*)buf; if(tp->cmd == lastCmd){ lastCount++; }else{ hsp_log(("send cmd:%04x, %d times\n", lastCmd, lastCount)); lastCmd = tp->cmd; lastCount = 1; } /* for sniffer use */ if(g_kernel.status.state != KERN_S_STANDBY){ memcpy((void*)buf,"PRIMRY",6); if(((struct peer_cmd_t*)buf)->cmd == 0x8002) __asm int 3; }else{
static __bool dumpBlk(ITreeNode * nd, __bool firstVisit, __uint context) { IBlk * b; FILE * of; b = __dcast__(ITreeNode, IBlk, nd); of = (FILE*)context; static int count; #if 0 fprintf(of, "#\n"); fprintf(of, "#-------BLK NO.%d----------------------\n", count++); fprintf(of, "#\n"); #endif if(b->h.magic == BBLK_MAGIC){ dumpBblk(b, of); }else{ dumpCblk(b, firstVisit, of); } return __true; }
static int ICommPeer_read(IPeer * _this, void * buf, int len, int to) { ICommPeer * __this; fd_set rset; struct timeval timeout; int ret; __this = __dcast__(IPeer, ICommPeer, _this); if(__this->hTty == ERROR){ return F8_INVALID_OPERATION; } FD_ZERO(&rset); FD_SET(__this->hTty, &rset); timeout.tv_sec = 0; timeout.tv_usec = to * 1000; ret = select(__this->hTty + 1, &rset, NULL, NULL, &timeout); if(FD_ISSET(__this->hTty, &rset)){ ret = read(__this->hTty, (char*)buf, len); }else{ ret = -1; } return ret; }
/* errors checked in this procedure 1) unattached DI with memory binding 2) DO without memory binding 3) DO with incorrect memory address 4) DO with conflicting address 5) multiple assignments of a variable */ __bool CErrorDetector::_fixup_pins(ITreeNode * nd) { IBlk * b; struct blk_pin_t * p; void * o; const struct blk_var_t * var; struct blk_pin_t * rp; int length; b = __dcast__(ITreeNode, IBlk, nd); for(p = __vcall__(b, first_pin, (b)); p; p = __vcall__(b, next_pin, (p))){ if(p->ulink){ continue; } rp = IBlk_real_pin(p); if(!(rp->_class == PIN_CLASS_DI || rp->_class == PIN_CLASS_DO)){ continue; } if(rp->_class == PIN_CLASS_DO && rp->binding != PIN_B_MEMORY){ // invalid binding CInvalidAddress ia; ia.magic = PIN_MAGIC; ia.o = rp; ia.a = 0; /* DO without MEMORY BINDING */ m_invalidAddress.insert(m_invalidAddress.end(), ia); } if(rp->binding != PIN_B_MEMORY){ continue; } length = _type_size(rp->type); var = (blk_var_t*)query_var_by_pin(p); if(!var){ if(rp->_class == PIN_CLASS_DI){ if(RtkIsTripleListEmpty(&rp->u1.link)){ CInvalidAddress ia; ia.magic = PIN_MAGIC; ia.o = rp; ia.a = 1; /* unattached DI with memory binding */ m_invalidAddress.insert(m_invalidAddress.end(), ia); } }else{ if(!is_address_valid(proxy_adapter->kernel, rp, &rp->u2.mem_addr)){ CInvalidAddress ia; ia.magic = PIN_MAGIC; ia.o = rp; ia.a = 2; /* invalid address */ m_invalidAddress.insert(m_invalidAddress.end(), ia); } CAddressConflit ac; /* check conflicts */ o = get_address_owner(&rp->u2.mem_addr, 1, &ac.magic2); if(o == rp){ continue; } ac.magic1 = PIN_MAGIC; ac.o1 = rp; ac.o2 = o; m_addrConflicts.insert(m_addrConflicts.end(), ac); } }else{ // the error is credited to the variable, not check here } } return __true; }
static void dumpCblk(IBlk * b, __bool firstVisit, FILE * of) { const char * name; char path[F8_MAX_PATH]; char buf[1024]; char idName[128]; struct blk_ent_t be; if(firstVisit){ name = IBlk_name(b); IBlk_path_by_blk(parent_blk(b), path, sizeof(path)); if(parent_blk(b) && !(parent_blk(b)->h.flags & BLK_F_READONLY)){ if(b->h.flags & BLK_F_READONLY){ if(blklib_query(&b->h.uuid, &be)){ sprintf(buf, "mount path=\"%s\" type=\"%s.%s\" name=\"%s\"", path, be.dir, be.name, name); }else{ f8_uuid_to_string(&b->h.uuid, idName, sizeof(idName)); sprintf(buf, "mount path=\"%s\" id=%s name=\"%s\"", path, idName, name); } if(of==stdout) utils_trace("%s\n",buf); else fprintf(of, "%s\n", buf); return; }else{ sprintf(buf, "mount path=\"%s\" file=blank.blk name=\"%s\" rw", path, name); } if (of==stdout) utils_trace("%s\n",buf); else fprintf(of, "%s\n", buf); IBlk_path_by_blk(b, path, sizeof(path)); sprintf(buf, "place block \"%s\" (%d,%d)", path, get_res_int(&b->uuid, "x", 0), get_res_int(&b->uuid, "y", 0)); if(of==stdout) utils_trace("%s\n",buf); else fprintf(of, "%s\n", buf); } enum_variables(b, defineVariable, (__uint)of); }else{ /* dump links positions/export pins */ if(b->h.flags & BLK_F_READONLY){ return; } ICBlk * cb = __dcast__(IBlk, ICBlk, b); struct cblk_link_t * l; for(l=ICBlk_first_link(cb); l; l=ICBlk_next_link(l)){ char p1[F8_MAX_PATH]; char p2[F8_MAX_PATH]; IBlk_path_by_pin(l->s.pin, p1, sizeof(p1)); IBlk_path_by_pin(l->t.pin, p2, sizeof(p2)); sprintf(buf, "link \"%s\" \"%s\"", p1, p2); if(of==stdout) utils_trace("%s\n",buf); else fprintf(of, "%s\n", buf); TLinkMetrics *m; m = (TLinkMetrics *)get_res_buf(&l->uuid, 0, "metrics"); if(m){ char *p; p = buf; p += sprintf(p, "place link \"%s\" %d ", p2, m->count); int i; for(i=0; i<m->count; i++){ p += sprintf(p, "(%d,%d) ", m->coord[i].x, m->coord[i].y); } if(of==stdout) utils_trace("%s\n",buf); else fprintf(of, "%s\n", buf); } } } }
/* patch the memory address in a block hive, and remember all register allocated. */ static __bool _alloc_reg_proc(ITreeNode * nd, __bool firstVisit, __uint context) { IBlk * b, *pb; struct blk_pin_t *p, *rp; CRegRequirementList * req; char path[1024]; blk_var_t * v; req = (CRegRequirementList*)context; b = __dcast__(ITreeNode, IBlk, nd); pb = parent_blk(b); for(p = __vcall__(b, first_pin, (b)); p; p = __vcall__(b, next_pin, (p)) ){ if(p->_class == PIN_CLASS_EI || p->_class == PIN_CLASS_EO){ continue; } if(p->ulink){ // postpone register allocation until the outmost // parent block is being processed continue; } // ok, do allocation rp = IBlk_real_pin(p); if(rp->binding == PIN_B_CONST){ if(rp->_class == PIN_CLASS_DI){ memcpy(rp->dp, p->dp, _type_size(rp->type)); continue; }else{ req->m_errcode = F8_INVALID_DATA; return __false; } }else if(rp->binding != PIN_B_MEMORY){ req->m_errcode = F8_INVALID_DATA; return __false; } if(pb && p->u2.mem_addr.section == MEM_SECTION_VAR){ // // the pin references a variable // if(v = (blk_var_t * )query_var_by_id(pb, p->u2.mem_addr.addr)){ // // note!! address is fixed on real pin // if(v->type != rp->type){ req->m_errcode = F8_INVALID_DATA; return __false; } rp->u2.mem_addr = v->addr; req->Add(v); }else{ IBlk_path_by_pin(p, path, sizeof(path)); utils_error( "%s references undefined variable %d.\n", path, p->u2.mem_addr.addr ); req->m_errcode = F8_UNRESOLVED_REFERENCES; return __false; } }else{ // // the pin has an address on its own // if(!req->Alloc(rp)){ return __false; } } } return __true; }
/* finding out registers usage info for the block hive */ static __bool _gather_reg_usage(ITreeNode * nd, __bool firstVisit, __uint context) { IBlk * b; struct blk_pin_t *p, *rp; int length; CRegRequirementList * req; struct blk_var_t * var; char pName[F8_MAX_PATH]; b = __dcast__(ITreeNode, IBlk, nd); req = (CRegRequirementList *)context; if(b->h.magic == CBLK_MAGIC && req->m_bGatherForDelete){ enum_variables(b, _e_var, (__uint)req); } for(p = __vcall__(b, first_pin, (b)); p; p = __vcall__(b, next_pin, (p))){ /* if the pin is exported, then the variable reference or memory address assignment is counted on the exported pins */ if(p->ulink){ continue; } rp = IBlk_real_pin(p); if(rp->_class != PIN_CLASS_DI && rp->_class != PIN_CLASS_DO){ continue; } if(rp->binding != PIN_B_MEMORY){ continue; } length = _type_size(rp->type); var = (blk_var_t*)query_var_by_pin(p); if(var){ req->Add(var); }else{ if(rp->_class == PIN_CLASS_DI){ if(RtkIsTripleListEmpty(&rp->u1.link)){ /* a data input pin can have a memory address only in two cases: 1) linked. or 2) connected with variable. */ IBlk_path_by_pin(p, pName, sizeof(pName)); utils_error( "%s - DI pin address %%%d%05d incorrect.\n", pName, rp->u2.mem_addr.section, rp->u2.mem_addr.addr ); req->m_errcode = F8_INVALID_DATA; } }else{ if(!is_address_valid(proxy_adapter->kernel, rp, &rp->u2.mem_addr)){ req->m_errcode = F8_INVALID_DATA; IBlk_path_by_pin(p, pName, sizeof(pName)); utils_error( "%s - DO pin address %%%d%05d incorrect.\n", pName, rp->u2.mem_addr.section, rp->u2.mem_addr.addr ); }else{ req->Add(rp, &rp->u2.mem_addr, length); } } } } return __true; }
/* ICBlk::load(IF8Stream * s) this will construct an in-memory composite block object. the most exciting part of F8 controller program. */ static __bool ICBlk_load(IBlk * blk, IF8Stream * s) { ICBlk * cblk; struct blk_hdr_t * h, _h; int i; IBlk * sb; union blk_pindef_t pd, ps, pt; f8_uuid uuid; cblk = __dcast__(IBlk, ICBlk, blk); h = &_h; if(__vcall__(s, get, (s, h, sizeof(struct blk_hdr_t))) != sizeof(struct blk_hdr_t) ) { return __false; } blk->h = *h; blk->h.u1.n_subblocks = 0; blk->h.u2.n_links = 0; blk->h.n_pins = 0; if(!__vcall__(s, get, (s, &blk->uuid, sizeof(blk->uuid)))) { goto __failed; } /* load sub-blocks */ for(i=0; i<h->u1.n_subblocks; i++) { sb = IBlk_from_stream(s); if(!sb) { goto __failed; } if(!ICBlk_add_blk(cblk, sb)) { delete_blk(sb); return __false; } } /* load links */ for(i=0; i<h->u2.n_links; i++) { if(!__vcall__(s, get, (s, &uuid, sizeof(uuid)))) { goto __failed; } if(!__vcall__(s, get, (s, &ps, sizeof(union blk_pindef_t)))) { goto __failed; } if(!__vcall__(s, get, (s, &pt, sizeof(union blk_pindef_t)))) { goto __failed; } locate_pin(blk, ps); locate_pin(blk, pt); if(!ps.pin || !pt.pin) { goto __failed; } if(!ICBlk_link(&uuid, ps.pin, pt.pin)) { goto __failed; } } /* load exports */ for(i=0; i<h->n_pins; i++) { if(!__vcall__(s, get, (s, &uuid, sizeof(uuid)))) { goto __failed; } if(!__vcall__(s, get, (s, &pd, sizeof(union blk_pindef_t)))) { goto __failed; } locate_pin(blk, pd); if(!pd.pin) { return __false; } if(!ICBlk_add_pin(&uuid, pd.pin)) { return __false; } } return __true; __failed: return __false; }