1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2% Copyright (c) 2017, ETH Zurich. 3% All rights reserved. 4% 5% This file is distributed under the terms in the attached LICENSE file. 6% If you do not find this file, copies can be found by writing to: 7% ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. 8% Attn: Systems Group. 9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 11:- module(decoding_net). 12:- export load_net/1. 13:- export decodes_to/2. 14:- export resolve/2. 15:- export node/2. 16 17:- dynamic node/2. 18:- export enum_translate_range/3. 19:- export name_to_enum/2. 20 21 22:- export struct(node(id:node_id,spec:node_spec)). 23:- export struct(node_id(name,namespace)). 24:- export struct(node_spec(type,accept,translate)). 25:- local struct(map(src_block,dest_node,dest_base,dest_props)). 26:- local struct(block(base,limit,props)). 27 28:- export struct(name(node_id:node_id,address)). 29:- export struct(region(node_id:node_id,base,size)). 30:- export struct(meta(node_id:node_id,key,value)). 31 32%% Used to enumerate names on nodes, to use them in capabilities. 33:- local struct(region_enum_block(node_id:node_id, in_base, in_limit, enum_base, enum_limit)). 34 35 36:- lib(ic). 37 38:- set_flag(syntax_option,based_bignums). 39:- set_flag(syntax_option,iso_base_prefix). 40 41:- dynamic meta/3. 42:- dynamic region_enum_block/5. 43 44%% Load a precompiled decoding net 45load_net(File) :- 46 ensure_loaded(File). 47 48%% Convert from regions to names 49to_name(Region,Name) :- 50 region{ 51 node_id:Id, 52 base:Base, 53 size:Size 54 } = Region, 55 Addr #>= Base, 56 Addr #< Base + Size, 57 Name = name{ 58 node_id:Id, 59 address:Addr 60 }. 61 62%% Convert from names to regions 63to_region(Name,Region) :- 64 name{ 65 node_id:Id, 66 address:Addr 67 } = Name, 68 get_bounds(Addr,Min,Max), 69 Size is Max - Min + 1, 70 ( get_domain_size(Addr,Size) -> 71 Region = region{ 72 node_id:Id, 73 base:Min, 74 size:Size 75 } 76 ; 77 writeln(stderr,"Name conversion to region failed: Non continuous domain for address"), 78 fail 79 ). 80 81%% Address range in block 82block_range(Block,Range) :- 83 block{ 84 base:Base, 85 limit:Limit 86 } = Block, 87 Range = Base..Limit. 88 89maps_to_name([Map|_],Addr,Name) :- 90 map{ 91 src_block:SrcBlock, 92 dest_node:Dest, 93 dest_base:DestBase 94 } = Map, 95 name{ 96 node_id:Dest, 97 address:DestAddr 98 } = Name, 99 block_range(SrcBlock,Range), 100 Addr :: Range, 101 block{base:SrcBase} = SrcBlock, 102 DestAddr #= Addr - SrcBase + DestBase. 103 104maps_to_name([_|Maps],Addr,Name) :- 105 maps_to_name(Maps,Addr,Name). 106 107translate(NodeSpec,Addr,Name) :- 108 node_spec{translate:Translate} = NodeSpec, 109 maps_to_name(Translate,Addr,Name). 110 111accept(NodeSpec,Addr) :- 112 node_spec{accept:Accept} = NodeSpec, 113 ( 114 foreach(Block,Accept), 115 fromto([],Prev,Next,Ranges) 116 do 117 block_range(Block,Range), 118 Next = [Range|Prev] 119 ), 120 Addr :: Ranges. 121 122accepted_name(Name) :- 123 name{ 124 node_id:NodeId, 125 address:Addr 126 } = Name, 127 node{ 128 id:NodeId, 129 spec:NodeSpec 130 }, 131 accept(NodeSpec,Addr). 132 133decode_step(SrcName,DestName) :- 134 name{ 135 node_id:NodeId, 136 address:Addr 137 } = SrcName, 138 node{ 139 id:NodeId, 140 spec:NodeSpec 141 }, 142 translate(NodeSpec,Addr,DestName). 143 144% Reflexive, transitive closure of decode_step 145decodes_to(SrcName,DestName) :- 146 SrcName = DestName. 147 148decodes_to(SrcName,DestName) :- 149 decode_step(SrcName,Name), 150 decodes_to(Name,DestName). 151 152resolve(SrcName,DestName) :- 153 name{} = SrcName, 154 name{} = DestName, 155 decodes_to(SrcName,DestName), 156 accepted_name(DestName). 157 158resolve(SrcRegion,DestRegion) :- 159 to_name(SrcRegion,SrcName), 160 to_name(DestRegion,DestName), 161 resolve(SrcName,DestName), 162 to_region(SrcName,SrcRegion), 163 to_region(DestName,DestRegion). 164 165ic_add_pred(A,B, R) :- 166 R #= A + B. 167 168enum_translate_range_block(NodeId, InBase, InLimit, EnumBase, EnumLimit) :- 169 region_enum_block(NodeId, InBase, InLimit, EnumBase, EnumLimit) ; 170 ( 171 findall((B,L), region_enum_block(_,_,_,B,L), LiPair), 172 ( 173 foreach((_,InL), LiPair), 174 foreach(InBound, LiBound) 175 do 176 InBound #= InL + 1 177 ), 178 maxlist([0|LiBound], MaxEnumBase), 179 180 EnumBase = MaxEnumBase, 181 EnumLimit #= EnumBase + InLimit - InBase, 182 assert(region_enum_block(NodeId, InBase, InLimit, EnumBase, EnumLimit)) 183 ). 184 185 186% enumerate all inputs of the nodeid. If one exists, return existing enumeration. 187% Assumes that accept and translate blocks are non overlapping. 188enum_translate_range(NodeId, Base, Limit) :- 189 node{id:NodeId, spec: node_spec{translate:TS}}, 190 %% Extract blocks from translate set 191 ( 192 foreach(TSSpec,TS), 193 foreach(RSSpec, RS) 194 do 195 TSSpec = map(block(Base, Limit, _), _, _, _), 196 RSSpec = (Base, Limit) 197 ), 198 199 %% TODO extract blocks from accept and append to Blocks 200 201 %% Pass blocks into enum_translate_range_block, return aggregate in 202 %% EnumBase and EnumLimit 203 ( 204 foreach((Base, Limit),RS), 205 param(NodeId), 206 foreach(EBase, EBaseList), 207 foreach(EMax, EMaxList) 208 do 209 enum_translate_range_block(NodeId, Base, Limit, EBase, ELimit), 210 EMax #= ELimit 211 ), 212 maxlist(EMaxList, Limit), 213 minlist(EBaseList, Base). 214 215name_to_enum(Name, EnumInt) :- 216 EBase #=< EnumInt, 217 EnumInt #=< ELimit, 218 region_enum_block(NodeId, Base, Limit, EBase, ELimit), 219 Addr #= Base + EnumInt - EBase, 220 Name = name{node_id:NodeId, address: Addr}. 221