add slids
[libreriscv.git] / overloadable_opcodes.mdwn
index 4d1e0e0a69c9dc74e214fe1c8ae9dd0123617bd3..ed05873e2d69d51ed347b39da40d5cb0c939ec97 100644 (file)
 # Overloadable opcodes. 
 
-This proposal adds a standardised extension instructions to the RV
-instruction set by introducing a fixed small number N (e.g. N = 8) of
-R-type opcodes xcmd0 rd, rs1, rs2, .. , xcmd<N> rd, rs1, rs2, that are intended to be used as "overloadable" (slightly crippled) R-type instructions for independently developed extensions in the form of non standard CPU extensions, IP tiles, or closely coupled external devices.
+The overloadable opcode (or xext) proposal allows a non standard extension to use a documented 20 + 3 bit   (or 52 + 3 bit on RV64) UUID identifier for an instruction for _software_ to use. At runtime, a cpu translates the UUID to a small implementation defined 12 + 3 bit bit identifier for _hardware_ to use. It also defines a fallback mechanism for the UUID's of instructions the cpu does not recognise.  
+
 Tl;DR see below for a C description of how this is supposed to work. 
+
+It defines a small number N  standardised R-type instructions 
+xcmd0, xcmd1, ...xcmd[N-1], preferably in the brownfield opcode space. We usually assume N = 8 (aka log2(8) = 3 in the + 3 above).  
+Each xcmd takes (in rs1) a 12 bit "logical unit" (lun) identifying a (sub)device on the cpu 
+that implements some "extension interface" (xintf) together with some additional data. 
+Extension devices may be implemented in any convenient form, e.g. non standard extensions 
+of the CPU iteself, IP tiles, or closely coupled external devices. 
+
+An xintf is a set of up to N commands with 2 input and 1 output port (i.e. like an 
+R-type instruction), together with a description of the semantics of the commands. Calling 
+e.g. xcmd3 routes its two inputs and one output ports to command 3 on the device determined 
+by the lun bits in rs1. Thus, the N standard xcmd instructions are standard-designated 
+overloadable opcodes, with the non standard semantics of the opcode determined by the lun. 
+
+Portable software, does not use luns directly. Instead, it goes through a level of 
+indirection using a further instruction xext. The xext instruction translates a 20 bit globally 
+unique identifier UUID of an xintf, to the lun of a device on the cpu that implements that xintf. 
+The cpu can do this, because it knows (at manufacturing or boot time) which devices it has, and 
+which xintfs they provide. This includes devices that would be described as non standard extension 
+of the cpu if the designers had used custom opcodes instead of xintf as an interface. If the 
+UUID of the xintf is not recognised at the current privilege level, the xext instruction returns 
+the special lun = 0, causing any xcmd to trap. Minor variations of this scheme (requiring two 
+more instructions xext0 and xextm1) cause xcmd instructions to fallback to always return 0 
+or -1 instead of trapping. 
+
+Remark1: the main difference with a previous "ioctl like proposal" is that UUID translation 
+is stateless and does not use resources. The xext instruction _neither_ initialises a 
+device _nor_ builds global state identified by a cookie. If a device needs initialisation 
+it can do this using xcmds as init and deinit instructions. Likewise, it can hand out 
+cookies (which can include the lun) as a return value .
+
+Remark2: Implementing devices can respond to an (essentially) arbitrary number of xintfs. 
+Hence, while an xintf is restricted to N commands, an implementing device can have an 
+arbitrary number of commands. Organising related commands in xintfs, helps avoid UUID space 
+pollution, and allows to amortise the (small) cost of UUID to lun translation if related 
+commands are used in combination.
  
-The input value of an xcmd instruction in rs2 is arbitrary. The content of the first input rs1, however, is divided in a 12bit "logical unit" (lun)  together with xlen - 12 bits of additional data. 
-The lun bits in rs1, determines a specific (sub)device, and the CPU routes the command to this device with rs1 and rs2 as input, and rd as output. Effectively, the xcmd0, ... xcmd7 instructions are "virtual method" opcodes, overloaded for different extension (sub)devices. 
+== Description of the instructions ==
+
+    xcmd0 rd, rs1, rs2
+    xcmd1 rd, rs1, rs2
+    ....
+    xcmdN rd, rs1, rs2
+
+* rs1 contains a 12 bit "logical unit" (lun)  together with xlen - 12 bits of additional data.
+* rs2 is arbitrary
+
+For e.g xmd3, route the inputs rs1, rs2 and output port rd to command 3 of the (sub)device on the cpu identified by the lun bits of rs1. 
+
+after execution:
+* rd contains the value that of the output port of the implementing device
 
-The specific value of the lun is supposed to be convenient for the cpu and is thus unstandardised. Portable software therefore constructs the lun, with a further R-type instruction xext. It takes a 20 bit universally unique identifier (UUID) that identifies  an interface with upto N R-type instructions with the signature of xcmd. An optional sequence number identifies a specific enumerated device on the cpu that implements the interface as a subdevice. For convenience, xext also or's bits rs2[0..XLEN-12]. If the UUID is not recognised 0 is returned. , but implemented by the extension (sub)device. Note that this scheme gives an easy work around the restriction on N (e.g. 8 ) commands: an implementing device can simply implement several interfaces as routable subdevices, indeed is expected to do so.  
+--------
+    xext  rd, rs1, rs2
+    xext0 rd, rs1, rs2
+    xextm1 rd, rs1, rs2
 
-The net effect is that a sequence like 
 
-    //fake UUID
-    lui   rd 0xEDCBA
+* rs1 contains 
+--a UUID of at least 20 bit in bit 12 .. XLEN of rs1 identifying an xintf.
+--the sequence number of a device at the current privilege level on the cpu implementing the xintf in bit 0..11 . 
+  In particular, if bit 0..11  is zero, the default implemententation is requested.
+* rs2 is arbitrary (but bit XLEN-12 to XLEN -1 is discarded)
+
+after execution,
+ if the cpu recognises the UUID and device at the current privilege level, rd contains the lun of a device 
+implementing the xintf in bit 0..11, followed by bit 0.. XLEN - 13 of rs2.
+if the cpu does not recognise the UUID and device it returns the numbers 0 (for xext), 1 (for xext0) or 2 (for xextm1), in particular bit 12.. XLEN are 0.
+
+---
+The net effect is that, when the CPU implements an xintf with UUID 0xABCDE a sequence like 
+
+    //fake UUID of an xintf
+    lui   rd 0xABCDE
     xext  rd rd rs1
     xcmd0 rd rd rs2 
 
-acts like a single namespaced instruction cmd0_EDCBA rd rs1 rs2 with the annoying caveat that rs1 can only use bits 0..XLEN-12 (the sequence is also not indivisible but the crucial semantics that you might want to be indivisible is in xcmd0). Delegation is expected to come at a small
-additional performance price compared to a "native" instruction. This should, however, be an acceptable tradeoff in many cases.
+acts like a single namespaced instruction cmd0_ABCDE rd rs1 rs2 (with the annoying caveat that the last 12 of rs1 are discarded) The sequence not indivisible but the crucial semantics that you might want to be indivisible is in xcmd0. 
+
+Delegation and UUID is expected to come at a small performance price compared to a "native" instruction. This should, however, be an acceptable tradeoff in many cases. Moreover implementations may opcode-fuse the whole instruction sequence or the first or last two instructions.
+If several instructions of the same interface are used, one can also use instruction sequences like 
+   
+    lui   t1 0xABCDE  //org_tinker_tinker__RocknRoll_uuid
+    xext  t1 t1 zero
+    xcmd0 a5, t1, a0  // org_tinker_tinker__RocknRoll__rock(a5, t1, a0) 
+    xcmd1 t2, t1, a1  // org_tinker_tinker__RocknRoll__roll(t2, t1, a5)
+    xcmd0 a0, t1, t2  // org_tinker_tinker__RocknRoll__rock(a0, t1, t2)
+If 0xABCDE is an unknown UUID at the current privilege level, the sequence results in a trap just like cmd0_ABCDE rd rs1 rs2 would. The sequence
+
+    //fake UUID of an xintf
+    lui   rd 0xABCDE
+    xext0  rd rd rs1
+    xcmd0 rd rd rs2 
 
+acts exactly like the sequence with xext, except that 0 is returned by xcmd0 if the UUID is unknown at the current privilege level. Likewise usage of xextm1  results in -1 being returned. This requires lun = 0 , 1 and 2 to be routed to three mandatory fallback 
+interfaces defined below.   
 
-Programatically the instructions in the interface are just a set of glorified assembler macros
+On the software level, the xintf is just a set of glorified assembler macros
 
      org.tinker.tinker:RocknRoll{
         uuid : 0xABCDE
@@ -30,15 +110,61 @@ Programatically the instructions in the interface are just a set of glorified as
         roll rd rs1 rs2 : xcmd1 rd rs1 rs2
      }
 
-so that the above sequence is more clearly written as 
+so that the above sequence can be more clearly written as 
 
     import(org.tinker.tinker:RocknRoll)
 
     lui rd org.tinker.tinker:RocknRoll:uuid
     xext rd rd rs1
     org.tinker.tinker:RocknRoll:rock rd rd rs2
+
     
-(Quite possibly even glorified standard assembler macros are overkill and it is easier to just use defines or ordinary macro's with long names. E.g. writing 
+------
+The following standard xintfs shall be implemented by the CPU.
+
+For lun == 0: 
+
+At  privilege level user mode, supervisor mode and hypervisor mode
+
+    org.RiscV:Fallback:Trap{
+        uuid: 0
+        trap0 rd rs1 rs2: xcmd0 rd rs1 rs2
+        ...
+        trap[N-1] rd rs1 rs2: xcmd[N-1] rd rs1 rs2
+    }
+
+each of the xcmd instructions shall trap to one level higher.
+
+At privilege level machine mode each trap command has unspecified behaviour, but in debug mode 
+should cause an exception to a debug environment.  
+
+For lun == 1, at all privilege levels
+
+    org.RiscV:Fallback:ReturnZero{
+        uuid: 1
+        return_zero0 rd rs1 rs2: xcmd0 rd rs1 rs2
+        ...
+        return_zero[N-1] rd rs1 rs2: xcmd[N-1] rd rs1 rs2
+    }
+
+each return_zero command shall return 0 in rd.
+
+For lun == 2, at all privilege levels
+
+    org.RiscV:Fallback:ReturnMinusOne{
+        uuid: 2
+        return_minusone0 rd rs1 rs2: xcmd0 rd rs1 rs2
+        ...
+        return_minusone[N-1] rd rs1 rs2: xcmd[N-1] rd rs1 rs2
+    }
+
+each return_minusone shall return -1.
+
+---
+
+Remark:
+Quite possibly even glorified standard assembler macros are overkill and it is 
+easier to just use defines or ordinary macro's with long names. E.g. writing 
 
     #define org_tinker_tinker__RocknRoll__uuid 0xABCDE 
     #define org_tinker_tinker__RocknRoll__rock(rd, rs1, rs2) xcmd0 rd, rs1, rs2
@@ -50,34 +176,24 @@ allows the same sequence to be written as
     xext  rd rs1
     org_tinker_tinker__RocknRoll__rock(rd, rd, rs2)
 
-Readability of assembler is no big deal for a compiler, but people are supposed to _document_ the interface and its semantics. In particular a semantics specified like the semantics of the cpu would be most welcome.)
-
-
-If several instructions of the same interface are used, one can also use instruction sequences like 
-   
-    lui   t1 org_tinker_tinker__RocknRoll_uuid
-    xext  t1 zero
-    xcmd0 a5, t1, a0  // org_tinker_tinker__RocknRoll__rock(a5, t1, a0) 
-    xcmd1 t2, t1, a1  // org_tinker_tinker__RocknRoll__roll(t2, t1, a5)
-    xcmd0 a0, t1, t2  // org_tinker_tinker__RocknRoll__rock(a0, t1, t2)
-
-This amortises the cost of the xext instruction. 
+Readability of assembler is no big deal for a compiler, but people are supposed 
+to _document_ the semantics of the interface. In particular specifying the semantics 
+of the xintf in same way as the semantics of the cpu should allow formal verification.
 
 ==Implications for the RiscV ecosystem ==
 
-
 The proposal allows independent groups to define one or more extension 
 interfaces of (slightly crippled) R-type instructions implemented by an 
 extension device. Such an extension device would be an native but non standard 
 extension of the CPU, an IP tile or a closely coupled external chip and would 
 be configured at manufacturing time or bootup of the CPU.
 
-Having a standardised overloadable interface simply avoids much of the
-need for isa extensions for hardware with non standard interfaces and
-semantics. This is analogous to the way that the standardised overloadable
-ioctl interface of the kernel almost completely avoids the need for
-extending the kernel with syscalls for the myriad of hardware devices
-with their specific interfaces and semantics.
+The 20 bit provided by the UUID of an xintf is much more room than provided by 
+the 2 custom 32 bit, or even 4 custom 64/48 bit opcode spaces. Thus the overloadable 
+opcodes proposal avoids most of the need to put a claim on opcode space,
+and the associated collisions when combining independent extensions. 
+In this respect it is similar to POSIX ioctls, which (almost) obviate the need for 
+defining new syscalls to control new or nonstandard hardware.
 
 The expanded flexibility comes at the cost: the standard can specify the
 semantics of the delegation mechanism and the interfacing with the rest
@@ -112,7 +228,7 @@ probabilities. On RV64 the UUID can also be extended to 52 bits (> 10^15).
        long uuid: 8*sizeof(long) - 12;
      } uuid_device_t
 
-     /* register format for rd of xext and rs1  for xcmd instructions, packs lun and data */
+     /* register format for rd of xext and rs1 of xcmd instructions, packs lun and data */
      typedef struct lun_data{
        long lun:12;
        long data: 8*sizeof(long) - 12;
@@ -175,23 +291,44 @@ probabilities. On RV64 the UUID can also be extended to 52 bits (> 10^15).
 
      /* 
        map (UUID, device, privilege) to a 12 bit lun, 
-       return (lun_t){0} on unknown  (at acces level)
+       return -1 on unknown  (at acces level)
 
        does associative memory lookup and tests privilege.
     */
     static
-    lun_t cpu__lookup_lun(const struct uuid_device_priv2lun* lun_map, uuid_dev_t uuid_dev, enum privilege priv);
+    short cpu__lookup_lun(const struct uuid_device_priv2lun* lun_map, uuid_dev_t uuid_dev, enum privilege priv, lun_t on_notfound);
 
 
+     #define org_RiscV__Trap__lun           ((lun_t)0)
+     #define org_RiscV__Fallback__ReturnZero__lun     ((lun_t)1)
+     #define org_RiscV__Fallback__ReturnMinusOne__lun ((lun_t)2)
 
      lun_data_t xext(uuid_dev_t rs1, long rs2)
      {
-        lun_t lun = cpu__lookup_lun(lun_map, rs1, current_privilege_level());
-
-        return (lun_data_t){.lun = lun.id, .data = rs2 % (1<< (8*sizeof(long) - 12))}
+        short lun = cpu__lookup_lun(lun_map, rs1, current_privilege_level(), org_RiscV__Fallback__Trap__lun);
+        if(lun < 0)
+             return (lun_data_t){.lun = org_RiscV__Fallback__Trap__lun, .data = 0};
+       
+        return (lun_data_t){.lun = lun, .data = rs2 % (1<< (8*sizeof(long) - 12))}
      }
 
+     lun_data_t xext0(uuid_dev_t rs1, long rs2)
+     {
+        short lun = cpu__lookup_lun(lun_map, rs1, current_privilege_level(), org_RiscV__Fallback__Trap__lun);
+        if(lun < 0)
+             return (lun_data_t){.lun = org_RiscV__Fallback__ReturnZero__lun, .data = 0};
+       
+        return (lun_data_t){.lun = lun, .data = rs2 % (1<< (8*sizeof(long) - 12))}
+     }
 
+     lun_data_t xextm1(uuid_dev_t rs1, long rs2)
+     {
+        short lun = cpu__lookup_lun(lun_map, rs1, current_privilege_level(), org_RiscV__Fallback__Trap__lun);
+        if(lun < 0)
+             return (lun_data_t){.lun = org_RiscV__Fallback__ReturnMinusOne__lun, .data = 0};
+       
+        return (lun_data_t){.lun = lun, .data = rs2 % (1<< (8*sizeof(long) - 12))}
+     }
 
 
      struct lun_priv2device_subdevice cpu__device_subdevice_map[];
@@ -203,24 +340,40 @@ probabilities. On RV64 the UUID can also be extended to 52 bits (> 10^15).
      device_subdevice_t cpu__lookup_device_subdevice(const struct lun_priv2device_subdevice_map* dev_subdev_map, 
                                                      lun_t lun, enum privileges priv);
 
+
+
      /* functional description of the delegating xcmd0 .. xcmd7 instructions */
-     template<k = 0..N-1> //pretend this is C
+     template<k = 0..N-1>   //pretend this is C
      long xcmd<k>(lun_data_t rs1, long rs2)
      {
          struct device_subdevice dev_subdev = cpu__lookup_device_subdevice(device_subdevice_map, rs1.lun, current_privilege());
-         if(dev_subdev.devAddr == NULL)
-            trap(“Illegal instruction”);
+        if(dev_subdev.devAddr == NULL)
+              cpu__trap_to(next_privilege); 
      
-         return dev_subdev.devAddr(dev_subdev.subdevId | k << 12, rs1, rs2);
+         return dev_subdev.devAddr(dev_subdev.subdevId | k >> 12 , rs1, rs2);
      }
 
+     /*Fallback interfaces*/
+     #define org_RiscV__Fallback__ReturnZero__uuid     1
+     #define org_RiscV__Fallback__ReturnMinusOne__uuid 2
 
+     /* fallback device */
+     static
+     long cpu__falback(short subdevice_xcmd,  lun_data_t rs1, long rs2)
+     {
+        switch(subdevice_xcmd % (1 << 12) ){
+        case 0  /* org.RiscV:ReturnZero */:   return 0;
+        case 1  /* org.RiscV:ReturnMinus1 */: return -1
+        default: trap("hardware configuration error");
+     }
 
 Example:
+
+     // Fake UUID's
      #define com_bigbucks__Frobate__uuid 0xABCDE
      #define org_tinker_tinker__RocknRoll__uuid 0x12345
-     #define org_tinker_tinker__Jazz__uuid 0xD0B0D
+     #define org_tinker_tinker__Jazz__uuid 0xBEB0B
      /*
      com.bigbucks:Frobate{
          uuid: com_bigbucks__Frobate__uuid
@@ -235,11 +388,16 @@ Example:
          roll rd rs1 rs2: cmd1 rd rs1 rs2
      }
 
+     /* 
+        Device 1 implements com.bigbucks::Frobate and org.tinker.tinker interfaces, uses 
+        a special command for the machine level implementation.  
+     */
+
      long com_bigbucks__device1(short  subdevice_xcmd, lun_data_t rs1, long rs2)
      {
         switch(subdevice_xcmd) {
         case 0 | 0 << 12  /* com.bigbucks:Frobate:frobate */     : return device1_frobate(rs1, rs2);
-        case 42| 0 << 12  /* com.bigbucks:FrobateMach:frobate    : return device1_frobate_machine_level(rs1, rs2);
+        case 0 | 7 << 12  /* com.bigbucks:Frobate:frobate */     : return device1_frobate_machine_level(rs1, rs2);
         case 0 | 1 << 12  /* com.bigbucks:Frobate:foo */         : return device1_foo(rs1, rs2);
         case 0 | 2 << 12  /* com.bigbucks:Frobate:bar */         : return device1_bar(rs1, rs2);
         case 1 | 0 << 12  /* org.tinker.tinker:RocknRoll:rock */ : return device1_rock(rs1, rs2);
@@ -255,6 +413,7 @@ Example:
      }
      */
 
+     /* Device 2 implements Frobate and Jazz interfaces */
      long org_tinker_tinker__device2(short subdevice_xcmd,  lun_data_t rs1, long rs2)
      {
         switch(dev_cmd.interfId){
@@ -266,54 +425,62 @@ Example:
         }
      }
 
-        /* struct uuid_dev2lun_map[] */  
-        lun_map = {     
-            {{.uuid_devId = {org_RiscV__Fallback__ReturnZero__uuid , 0},    .priv = user},  .lun =  1},
-            {{.uuid_devId = {org_RiscV__Fallback__ReturnZero__uuid , 0},    .priv = super}, .lun =  1},
-            {{.uuid_devId = {org_RiscV__Fallback__ReturnZero__uuid , 0},    .priv = hyper}, .lun =  1},
-            {{.uuid_devId = {org_RiscV__Fallback__ReturnZero__uuid , 0},    .priv = mach}   .lun =  1},   
-            {{.uuid_devId = {org_RiscV__Fallback__ReturnMinusOne__uuid, 0}, .priv = user},  .lun =  2},
-            {{.uuid_devId = {org_RiscV__Fallback__ReturnMinusOne__uuid, 0}, .priv = super}, .lun =  2},
-            {{.uuid_devId = {org_RiscV__Fallback__ReturnMinusOne__uuid, 0}, .priv = hyper}, .lun =  2},
-            {{.uuid_devId = {org_RiscV__Fallback__ReturnMinusOne__uuid, 0}, .priv = mach},  .lun =  2},
-            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 0},               .priv = user}   .lun = 32},  //32 sic!
-            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 1},               .priv = super}  .lun = 32},
-            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 1},               .priv = hyper}  .lun = 32},
-            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 1},               .priv = mach}   .lun = 32},
-            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 0},               .priv = super}  .lun = 34},  //34 sic!
-            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 0},               .priv = hyper}  .lun = 34},  
-            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 0},               .priv = mach}   .lun = 34},  
-            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = user}   .lun = 33},  //33 sic!
-            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = super}  .lun = 33},  
-            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = hyper}  .lun = 33},  
-            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = super}, .lun = 35},
-            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = hyper}, .lun = 35},
+     /* cpu assigns luns to the interfaces at different privilege levels on device1 and 2 to luns at manufacturing or boot up time */
+     #define cpu__Device1__Frobate__lun   ((lun_t)32)
+     #define cpu__Device1__RocknRoll__lun ((lun_t)33)
+     #define cpu__Device2__Frobate__lun   ((lun_t)34)
+     #define cpu__Device2__Jazz__lun      ((lun_t)35)
+
+     /* struct uuid_dev2lun_map[] */  
+     lun_map = {     
+            {{.uuid_devId = {org_RiscV__Fallback__ReturnZero__uuid , 0},    .priv = user},  .lun = org_RiscV__Fallback__ReturnZero__lun},
+            {{.uuid_devId = {org_RiscV__Fallback__ReturnZero__uuid , 0},    .priv = super}, .lun = org_RiscV__Fallback__ReturnZero__lun},
+            {{.uuid_devId = {org_RiscV__Fallback__ReturnZero__uuid , 0},    .priv = hyper}, .lun = org_RiscV__Fallback__ReturnZero__lun},
+            {{.uuid_devId = {org_RiscV__Fallback__ReturnZero__uuid , 0},    .priv = mach}   .lun = org_RiscV__Fallback__ReturnZero__lun},   
+            {{.uuid_devId = {org_RiscV__Fallback__ReturnMinusOne__uuid, 0}, .priv = user},  .lun = org_RiscV__Fallback__ReturnMinusOne__lun},
+            {{.uuid_devId = {org_RiscV__Fallback__ReturnMinusOne__uuid, 0}, .priv = super}, .lun = org_RiscV__Fallback__ReturnMinusOne__lun},
+            {{.uuid_devId = {org_RiscV__Fallback__ReturnMinusOne__uuid, 0}, .priv = hyper}, .lun = org_RiscV__Fallback__ReturnMinusOne__lun},
+            {{.uuid_devId = {org_RiscV__Fallback__ReturnMinusOne__uuid, 0}, .priv = mach},  .lun = org_RiscV__Fallback__ReturnMinusOne__lun},
+            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 0},               .priv = user}   .lun = cpu__Device1__Frobate__lun}, 
+            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 1},               .priv = super}  .lun = cpu__Device1__Frobate__lun},
+            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 1},               .priv = hyper}  .lun = cpu__Device1__Frobate__lun},
+            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 1},               .priv = mach}   .lun = cpu__Device1__Frobate__lun},
+            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 0},               .priv = super}  .lun = cpu__Device2__Frobate__lun},  
+            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 0},               .priv = hyper}  .lun = cpu__Device2__Frobate__lun},  
+            {{.uuid_devId = {com_bigbucks__Frobate__uuid, 0},               .priv = mach}   .lun = cpu__Device2__Frobate__lun},  
+            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = user}   .lun = cpu__Device1__RocknRoll__lun}, 
+            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = super}  .lun = cpu__Device1__RocknRoll__lun},  
+            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = hyper}  .lun = cpu__Device1__RocknRoll__lun},  
+            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = super}, .lun = cpu__Device2__Jazz__lun},
+            {{.uuid_devId = {org_tinker_tinker__RocknRoll__uuid, 0},        .priv = hyper}, .lun = cpu__Device2__Jazz__lun},
        }
    
+     /* cpu maps luns + privilege level to busaddress of device and particular subdevice according to spec of the device.*/
      /* struct lun2dev_subdevice_map[] */
         dev_subdevice_map = {
-      //     {.lun = 0,   error and falls back to trapping xcmd 
-             {{.lun = 1, .priv = user},  .devAddr_interfId = {fallback,    0 /* ReturnZero  */}},
-             {{.lun = 1, .priv = super}, .devAddr_interfId = {fallback,    0 /* ReturnZero  */}},
-             {{.lun = 1, .priv = hyper}, .devAddr_interfId = {fallback,    0 /* ReturnZero  */}},
-             {{.lun = 1, .priv = mach},  .devAddr_interfId = {fallback,    0 /* ReturnZero  */}},
-             {{.lun = 2, .priv = user},  .devAddr_interfId = {fallback,    1 /* ReturnMinusOne*/}},
-             {{.lun = 2, .priv = super}, .devAddr_interfId = {fallback,    1 /* ReturnMinusOne*/}},
-             {{.lun = 2, .priv = hyper}, .devAddr_interfId = {fallback,    1 /* ReturnMinusOne*/}},
-             {{.lun = 2, .priv = mach},  .devAddr_interfId = {fallback,    1 /* ReturnMinusOne*/}},
+    //         .lun = 0,  will trap 
+             {{.lun = org_RiscV__Fallback__ReturnZero__lun,     .priv = user},  .devAddr_interfId = {fallback,    1 /* ReturnZero  */}},
+             {{.lun = org_RiscV__Fallback__ReturnZero__lun,     .priv = super}, .devAddr_interfId = {fallback,    1 /* ReturnZero  */}},
+             {{.lun = org_RiscV__Fallback__ReturnZero__lun,     .priv = hyper}, .devAddr_interfId = {fallback,    1 /* ReturnZero  */}},
+             {{.lun = org_RiscV__Fallback__ReturnZero__lun,     .priv = mach},  .devAddr_interfId = {fallback,    1 /* ReturnZero  */}},
+             {{.lun = org_RiscV__Fallback__ReturnMinusOne__lun, .priv = user},  .devAddr_interfId = {fallback,    2 /* ReturnMinusOne*/}},
+             {{.lun = org_RiscV__Fallback__ReturnMinusOne__lun, .priv = super}, .devAddr_interfId = {fallback,    2 /* ReturnMinusOne*/}},
+             {{.lun = org_RiscV__Fallback__ReturnMinusOne__lun, .priv = hyper}, .devAddr_interfId = {fallback,    2 /* ReturnMinusOne*/}},
+             {{.lun = org_RiscV__Fallback__ReturnMinusOne__lun, .priv = mach},  .devAddr_interfId = {fallback,    2 /* ReturnMinusOne*/}},
      //       .lun = 3 .. 7  reserved for other fallback RV interfaces
      //       .lun = 8 .. 30 reserved as error numbers, c.li t1 31; bltu rd t1 L_fail tests errors
-     //      .lun = 31  reserved out of caution 
-             {{.lun = 32, .priv = user},  .devAddr_interfId = {device1, 0 /* Frobate  interface */}},
-             {{.lun = 32, .priv = super}, .devAddr_interfId = {device1, 0 /* Frobate  interface */}},
-             {{.lun = 32, .priv = hyper}, .devAddr_interfId = {device1, 0 /* Frobate  interface */}},
-             {{.lun = 32, .priv = mach},  .devAddr_interfId = {device1,64 /* Frobate  machine level interface */}},
-             {{.lun = 33, .priv = user},  .devAddr_InterfId = {device1, 1 /* RocknRoll interface */}},
-             {{.lun = 33, .priv = super}, .devAddr_InterfId = {device1, 1 /* RocknRoll interface */}},
-             {{.lun = 33, .priv = hyper}, .devAddr_InterfId = {device1, 1 /* RocknRoll interface */}},
-             {{.lun = 34, .priv = super}, .devAddr_interfId = {device2, 0 /* Frobate interface */}},
-             {{.lun = 34, .priv = hyper}, .devAddr_interfId = {device2, 0 /* Frobate interface */}},
-             {{.lun = 34, .priv = mach},  .devAddr_interfId = {device2, 0 /* Frobate interface */}},
-             {{.lun = 35, .priv = super}, .devAddr_interfId = {device2, 1 /* Jazz interface */}},
-             {{.lun = 35, .priv = hyper}, .devAddr_interfId = {device2, 1 /* Jazz interface */}},
+     //       .lun = 31  reserved out of caution 
+             {{.lun = cpu__Device1__Frobate__lun,               .priv = user},  .devAddr_interfId = {device1, 0 /* Frobate  interface */}},
+             {{.lun = cpu__Device1__Frobate__lun,               .priv = super}, .devAddr_interfId = {device1, 0 /* Frobate  interface */}},
+             {{.lun = cpu__Device1__Frobate__lun,               .priv = hyper}, .devAddr_interfId = {device1, 0 /* Frobate  interface */}},
+             {{.lun = cpu__Device1__Frobate__lun,               .priv = mach},  .devAddr_interfId = {device1,64 /* Frobate  machine level */}},
+             {{.lun = cpu__Device1__RocknRoll__lun,             .priv = user},  .devAddr_InterfId = {device1, 1 /* RocknRoll interface */}},
+             {{.lun = cpu__Device1__RocknRoll__lun,             .priv = super}, .devAddr_InterfId = {device1, 1 /* RocknRoll interface */}},
+             {{.lun = cpu__Device1__RocknRoll__lun,             .priv = hyper}, .devAddr_InterfId = {device1, 1 /* RocknRoll interface */}},
+             {{.lun = cpu__Device1__RocknRoll__lun,             .priv = super}, .devAddr_interfId = {device2, 1 /* Frobate interface */}},
+             {{.lun = cpu__Device2__Frobate__lun,               .priv = super}, .devAddr_interfId = {device2, 0 /* Frobate interface */}},
+             {{.lun = cpu__Device2__Frobate__lun,               .priv = hyper}, .devAddr_interfId = {device2, 0 /* Frobate interface */}},
+             {{.lun = cpu__Device2__Frobate__lun,               .priv = mach},  .devAddr_interfId = {device2, 0 /* Frobate interface */}},
+             {{.lun = cpu__Device2__Jazz__lun,                  .priv = super}, .devAddr_interfId = {device2, 1 /* Jazz interface */}},
+             {{.lun = cpu__Device2__Jazz__lun,                  .priv = hyper}, .devAddr_interfId = {device2, 1 /* Jazz interface */}},
          }