From 1827323db70f3cb2e2b33ef26461a188993360dc Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sat, 8 Jun 2019 17:46:38 -0700 Subject: [PATCH 01/26] start rfmap composing --- verification/refinement.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/verification/refinement.md b/verification/refinement.md index a55850a..b7666a2 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -1,2 +1,16 @@ # Refinement Relation + +The refinement map or refinement relation mainly consists of two parts: _variable mappings_ and +_instruction completion conditions_. These two parts are specified in two separate files, one +referred as _var-map_ and the other _inst-cond_. + + +Besides the above two parts, there are other auxiliary information needed. They are: + + - **module naming**: The names of the ILA module and the Verilog module. + - **global invariants**: Some properties that are globally true for the Verilog design that will be checked separately and can be safely assumed when verifying individual instructions. + - **interface signal information**: What does the interface of the Verilog top module look like and what do these signals mean to the tool. + - **uninterpreted function mapping**: What an uninterpreted function inside the ILA model corresponds to. + +### The Structure of _var-map_ and _inst-cond_ ### \ No newline at end of file From 9bf807caf62045b023b4cb7578ad077ec1b7c31b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sat, 8 Jun 2019 17:54:22 -0700 Subject: [PATCH 02/26] test json code --- verification/refinement.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/verification/refinement.md b/verification/refinement.md index b7666a2..1cc64c3 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -13,4 +13,34 @@ Besides the above two parts, there are other auxiliary information needed. They - **interface signal information**: What does the interface of the Verilog top module look like and what do these signals mean to the tool. - **uninterpreted function mapping**: What an uninterpreted function inside the ILA model corresponds to. -### The Structure of _var-map_ and _inst-cond_ ### \ No newline at end of file +### The Structure of _var-map_ and _inst-cond_ ### + +```json +{ + "models": { + "ILA" : , + "VERILOG": }, + "state mapping": { + : , + ... + }, + "interface mapping": { + : , + ... + }, + "mapping control": [ + , + ... + ], + "functions":{ + : + [ + [ + , , + , , + ... + ] + ] + } +} +``` From d6e65b88395c21c3c8897cd159bec659f1248a85 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sat, 8 Jun 2019 18:19:13 -0700 Subject: [PATCH 03/26] inst-cond --- verification/refinement.md | 95 ++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 13 deletions(-) diff --git a/verification/refinement.md b/verification/refinement.md index 1cc64c3..a8daa0a 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -13,34 +13,103 @@ Besides the above two parts, there are other auxiliary information needed. They - **interface signal information**: What does the interface of the Verilog top module look like and what do these signals mean to the tool. - **uninterpreted function mapping**: What an uninterpreted function inside the ILA model corresponds to. -### The Structure of _var-map_ and _inst-cond_ ### +### The Structure of _var-map_ ### + ```json { "models": { - "ILA" : , - "VERILOG": }, + "ILA" : "" , + "VERILOG": "" }, "state mapping": { - : , - ... + "" : "", + // more ... }, "interface mapping": { - : , - ... + "" : "", + // more ... }, "mapping control": [ - , - ... + "", + // more ... ], "functions":{ - : + "": [ [ - , , - , , - ... + "", "", + "", "", + // more ... ] ] } } ``` + +### The Structure of _inst-cond_ ### + +```json +{ + "instructions": + [ + { + "instruction" :"", + "ready bound" :12345, // + "ready signal" :"", + "max bound" :12345, // + "start condition" :"", + "flush constraint":"", + "pre-flush end" :"", + "post-flush end" :"" + } + ] +} +``` + + +### Module Naming ### + +The module naming section comes first in the _var-map_ JSON file. It is a dictionary (map) with two elements. One element should have the key `ILA` and the value of it is what will be used as the instance name of the ILA module. The other element should have the key `VERILOG` with the value to be the instance name of the Verilog module. These names are used in all the expressions later when you want to refer to a variable in Verilog or ILA. + +### Variable Mapping ### + +The variable mapping in the JSON file is a map data structure. The keys of this map are the state variable names in the ILA model while the values are the Verilog variables. There are cases that one Verilog state variable can be mapped to multiple Verilog state variables and the mapping may be some special function. So the allowed value field of this map can be: + + 1. A Verilog variable name as a string. If the Verilog variable is in the top module of Verilog, you can omit the module name (it does not hurt to add it). Otherwise, you must specify the complete hierarchy. For example, if you want to refer to a signal \texttt{S} in module \texttt{A} that is instantiated with name \texttt{IA} in the top module, while the top module's instance name is \texttt{VERILOG} (specified in the previous section), then you should use \texttt{VERILOG.IA.S} to refer to it. + + 2. A predicate that has at least a `=` in it (you can use `>=` , `<=` , `==` and etc.) This is just for our parser to distinguish it from the first case + + 3. A string-string pair that is in the form of a list or map. If it is given as a list, the first element is regarded as the condition and the second element is regarded as the mapping. It conveys the meaning of "when the condition is true, the ILA and Verilog variables should have the mapping". If the condition is not true, there is no mapping guaranteed. If the string-string pair is given as a map, it must have two elements. One element should have the key `cond` and the other should have the key `map`. The `map` part could be a string of Verilog variable name as in case (1) or a Verilog expression as case (2). + + 4. A list of string-string pairs, each pair follows requirement in (3). + +Below are some of the examples: +```json +{ + "state mapping": { + "ILA_state_1" : "Verilog_state_1", // case 1 + "ILA_state_2" : "ILA_state_2 == Verilog_state_2 + Verilog_state_3", // case 2 + "ILA_state_3" : ["__START__", "Verilog_state_3"], // case 3.a + "ILA_state_4" : { "cond":"__START__", "map":"Verilog_state_4"}, // case 3.b + "ILA_state_5" : [["__START__", "Verilog_state_5"], ["__IEND__","Verilog_state_6"]], // case 4 + // more ... + }, + // other fields ... +} +``` + +One note in the above example: the condition can refer to special signals (`__START__ ` and `__IEND__`), which are the condition when the instruction-under-verification starts to execute and finishes. + +### Instruction Completion Condition ### + + +The instruction completion condition is specified per instruction. In the JSON file, it is a list of maps. The list does not need to be a full list of instructions. Those not in the list will not be verified. Each dictionary must have an element whose key is `instruction` and the value of this element is the name of the instruction in the ILA model. Besides this name element, it must contain one of the `ready bound` or the `ready signal` element. The `ready bound` specifies a bound that the instruction takes. It is used for instructions that take a fixed number of cycles. Alternatively, one can provide a signal (or a predicate) in the `ready signal` field. + +There are several optional fields. They are `start condition`, `max bound`, `flush constraint`, `pre flush-end` and `post flush-end`. + +The `start condition` field, if provided, should be a list of strings. Each string is a Verilog expression that acts as a predicate on the Verilog design. It can be used to constrain the Verilog implementation state, because usually there are more microarchitectural (implementation states) in the design. For the starting state of an instruction, these microarchitectural states should be `consistent` with the visible states in the ILA, and you can use this field to enforce the `consistency` at your discretion. You can use `$decode$` and `$valid$` to refer to the instruction's decode function or its ILA valid condition. + +The `max bound` can be used when `ready signal` field is provided. It provides an assumption that the condition that the `ready signal` field specified will occur in the given number of cycles, and this will limit the model checking to that bound. Usually this is used for the additional environment assumptions about the input (for example, how many cycles at most there are for a request to be served with a response). + +The `flush constraint`, `pre flush-end` and `post flush-end` signals are used when using the `flushing verification setting`. For this verification setting, you can refer to \href{https://arxiv.org/abs/1801.01114}{our paper} on the ILA-based verification or the \href{https://dl.acm.org/citation.cfm?id=735662}{Burch-Dill's approach} on processor verification. + From 2d5eead7fe6d9bb8e8aa459b34347a2e05cfeec3 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 9 Jun 2019 12:09:42 -0700 Subject: [PATCH 04/26] done rfmap --- verification/refinement.md | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/verification/refinement.md b/verification/refinement.md index a8daa0a..dff2d60 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -113,3 +113,55 @@ The `max bound` can be used when `ready signal` field is provided. It provides a The `flush constraint`, `pre flush-end` and `post flush-end` signals are used when using the `flushing verification setting`. For this verification setting, you can refer to \href{https://arxiv.org/abs/1801.01114}{our paper} on the ILA-based verification or the \href{https://dl.acm.org/citation.cfm?id=735662}{Burch-Dill's approach} on processor verification. + +### Global Invariants ### + +In the verification of instructions, we do not assume the design starts from the initial states. This helps us to get a better guarantee of the instruction correctness when only bounded model checking is used. However, if there is no constraints on the starting state of a instruction, there +might be spurious bugs just because the design starts from a state that it will never reach when started from the reset state. In order to avoid this false positive, we use global invariants to constrain on the starting state. These invariants help rule out some unreachable states and the tool will generate a separate target to check whether the provided invariants are globally true or not. These invariants should be provided as a list of strings, where each string is a Verilog predicate. In the future, we will exploit invariant synthesis techniques to help synthesize these invariants. + +### Interface Signal Information ### + +The Verilog module comes with a set of I/O signals and the tool needs to know how these signals should be connected. The `interface mapping` field is a map whose keys are the Verilog I/O signal names and whose values can be one of the following: + + * An ILA input name. This means that the Verilog input signal corresponds to one ILA input. They must have the same encoding and bit-width. + * `**KEEP**` directive. Telling the tool to have a wire of the same name and to connect it as the verification wrapper I/O. + * `**NC**` directive, indicating that this port does not need to be connected. + * `**SO**` directive, indicating that this is actually a direct output from a visible state variable (a state variable that is modeled in the ILA). + * `**RESET**` or `**NRESET**` directive. Indicating that this signal is the reset signal, active-high or active-low (we assume synchronous reset). + * `**CLOCK**` directive, indicating that this is the clock signal. + * `**MEM**name.signal` directive, indicating this signal is the connection to an external/shared memory. The name part should be the ILA state variable name of the memory, and the signal part could be one of the following: `wdata`,`rdata`, `waddr`,`raddr`, `wen`, `ren`. If the signal does not directly correspond to the write/read data, write/read address, write/read enable signal, it should be specified as `**KEEP**`, you can specify the mapping using the additional assumptions. + +### Uninterpreted Function Mapping ### + +The ILA model may use uninterpreted functions, however, in the verification, the tool must know the correspondence of this uninterpreted function in order to reason about the correctness. In the `functions` field of the _var-map_ JSON, a map should be provided if uninterpreted function is used in the ILA model. The keys of the map are the function names, with the values in a list. Each element of this list is for one application of this function. Per each function application, the tool needs to know the correspondence of the arguments/result in the Verilog and when that happens, this is like a condition/mapping pair, and it is specified as a list. The correspondence of the function result goes first followed by the arguments (in the same order as the arguments in ILA function definitions). + +For example in the ILA there is such specification +```cpp + auto div = FuncRef("div", SortRef::BV(8), SortRef::BV(8), SortRef::BV(8) ); + instr.SetUpdate(state0, div(arg0, arg1) ); +``` + +Then in the refinement map +```json +{ + "functions" : { + "div" : [ ["cond1", "verilog-signal-result", "cond2", "verilog-signal-arg0", "cond3", "verilog-signal-arg1", ] ] + } +} +``` + +### Additional Assumptions ### + + +This section allows users to add additional assumptions in the verification. They can be, for example, + + * An assumption about the module I/O. + * A mapping from the Verilog design's memory interface to the provided 6-signal memory interface. The AES case study provides an example of this. The Verilog design uses two signals `stb` and `wr` to indicate memory read and write enable, which are different from the `ren` and `wen` signals. Therefore a mapping is provided as follows: + +```json + +"mapping control" : [ + "( wr & stb) == "__MEM_XRAM_0_wen" , + "(~wr & stb) == "__MEM_XRAM_0_ren" ] +``` + From 61fcf46ccca2d7b77f5798efe57e183681f9ec89 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 9 Jun 2019 12:18:27 -0700 Subject: [PATCH 05/26] fix style --- verification/refinement.md | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/verification/refinement.md b/verification/refinement.md index dff2d60..ea3b92e 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -1,11 +1,9 @@ # Refinement Relation - The refinement map or refinement relation mainly consists of two parts: _variable mappings_ and _instruction completion conditions_. These two parts are specified in two separate files, one referred as _var-map_ and the other _inst-cond_. - Besides the above two parts, there are other auxiliary information needed. They are: - **module naming**: The names of the ILA module and the Verilog module. @@ -15,7 +13,6 @@ Besides the above two parts, there are other auxiliary information needed. They ### The Structure of _var-map_ ### - ```json { "models": { @@ -66,7 +63,6 @@ Besides the above two parts, there are other auxiliary information needed. They } ``` - ### Module Naming ### The module naming section comes first in the _var-map_ JSON file. It is a dictionary (map) with two elements. One element should have the key `ILA` and the value of it is what will be used as the instance name of the ILA module. The other element should have the key `VERILOG` with the value to be the instance name of the Verilog module. These names are used in all the expressions later when you want to refer to a variable in Verilog or ILA. @@ -75,12 +71,9 @@ The module naming section comes first in the _var-map_ JSON file. It is a dictio The variable mapping in the JSON file is a map data structure. The keys of this map are the state variable names in the ILA model while the values are the Verilog variables. There are cases that one Verilog state variable can be mapped to multiple Verilog state variables and the mapping may be some special function. So the allowed value field of this map can be: - 1. A Verilog variable name as a string. If the Verilog variable is in the top module of Verilog, you can omit the module name (it does not hurt to add it). Otherwise, you must specify the complete hierarchy. For example, if you want to refer to a signal \texttt{S} in module \texttt{A} that is instantiated with name \texttt{IA} in the top module, while the top module's instance name is \texttt{VERILOG} (specified in the previous section), then you should use \texttt{VERILOG.IA.S} to refer to it. - + 1. A Verilog variable name as a string. If the Verilog variable is in the top module of Verilog, you can omit the module name (it does not hurt to add it). Otherwise, you must specify the complete hierarchy. For example, if you want to refer to a signal `S` in module `A` that is instantiated with name `IA` in the top module, while the top module's instance name is `VERILOG` (specified in the previous section), then you should use `VERILOG.IA.S` to refer to it. 2. A predicate that has at least a `=` in it (you can use `>=` , `<=` , `==` and etc.) This is just for our parser to distinguish it from the first case - 3. A string-string pair that is in the form of a list or map. If it is given as a list, the first element is regarded as the condition and the second element is regarded as the mapping. It conveys the meaning of "when the condition is true, the ILA and Verilog variables should have the mapping". If the condition is not true, there is no mapping guaranteed. If the string-string pair is given as a map, it must have two elements. One element should have the key `cond` and the other should have the key `map`. The `map` part could be a string of Verilog variable name as in case (1) or a Verilog expression as case (2). - 4. A list of string-string pairs, each pair follows requirement in (3). Below are some of the examples: @@ -102,7 +95,6 @@ One note in the above example: the condition can refer to special signals (`__ST ### Instruction Completion Condition ### - The instruction completion condition is specified per instruction. In the JSON file, it is a list of maps. The list does not need to be a full list of instructions. Those not in the list will not be verified. Each dictionary must have an element whose key is `instruction` and the value of this element is the name of the instruction in the ILA model. Besides this name element, it must contain one of the `ready bound` or the `ready signal` element. The `ready bound` specifies a bound that the instruction takes. It is used for instructions that take a fixed number of cycles. Alternatively, one can provide a signal (or a predicate) in the `ready signal` field. There are several optional fields. They are `start condition`, `max bound`, `flush constraint`, `pre flush-end` and `post flush-end`. @@ -111,7 +103,7 @@ The `start condition` field, if provided, should be a list of strings. Each stri The `max bound` can be used when `ready signal` field is provided. It provides an assumption that the condition that the `ready signal` field specified will occur in the given number of cycles, and this will limit the model checking to that bound. Usually this is used for the additional environment assumptions about the input (for example, how many cycles at most there are for a request to be served with a response). -The `flush constraint`, `pre flush-end` and `post flush-end` signals are used when using the `flushing verification setting`. For this verification setting, you can refer to \href{https://arxiv.org/abs/1801.01114}{our paper} on the ILA-based verification or the \href{https://dl.acm.org/citation.cfm?id=735662}{Burch-Dill's approach} on processor verification. +The `flush constraint`, `pre flush-end` and `post flush-end` signals are used when using the `flushing verification setting`. For this verification setting, you can refer to [our paper](https://arxiv.org/abs/1801.01114) on the ILA-based verification or the [Burch-Dill's approach](https://dl.acm.org/citation.cfm?id=735662) on processor verification. ### Global Invariants ### @@ -161,7 +153,6 @@ This section allows users to add additional assumptions in the verification. The ```json "mapping control" : [ - "( wr & stb) == "__MEM_XRAM_0_wen" , - "(~wr & stb) == "__MEM_XRAM_0_ren" ] + "( wr & stb) == __MEM_XRAM_0_wen" , + "(~wr & stb) == __MEM_XRAM_0_ren" ] ``` - From f5df913df3cc80533bb7f6151a2e710eea43ad79 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 9 Jun 2019 12:22:18 -0700 Subject: [PATCH 06/26] style fix 2 --- verification/refinement.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/verification/refinement.md b/verification/refinement.md index ea3b92e..76a31f4 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -6,12 +6,12 @@ referred as _var-map_ and the other _inst-cond_. Besides the above two parts, there are other auxiliary information needed. They are: - - **module naming**: The names of the ILA module and the Verilog module. - - **global invariants**: Some properties that are globally true for the Verilog design that will be checked separately and can be safely assumed when verifying individual instructions. - - **interface signal information**: What does the interface of the Verilog top module look like and what do these signals mean to the tool. - - **uninterpreted function mapping**: What an uninterpreted function inside the ILA model corresponds to. + * **module naming**: The names of the ILA module and the Verilog module. + * **global invariants**: Some properties that are globally true for the Verilog design that will be checked separately and can be safely assumed when verifying individual instructions. + * **interface signal information**: What does the interface of the Verilog top module look like and what do these signals mean to the tool. + * **uninterpreted function mapping**: What an uninterpreted function inside the ILA model corresponds to. -### The Structure of _var-map_ ### +### The Structure of Variable Mappings ### ```json { @@ -43,7 +43,7 @@ Besides the above two parts, there are other auxiliary information needed. They } ``` -### The Structure of _inst-cond_ ### +### The Structure of Instruction Completion Conditions ### ```json { @@ -105,7 +105,6 @@ The `max bound` can be used when `ready signal` field is provided. It provides a The `flush constraint`, `pre flush-end` and `post flush-end` signals are used when using the `flushing verification setting`. For this verification setting, you can refer to [our paper](https://arxiv.org/abs/1801.01114) on the ILA-based verification or the [Burch-Dill's approach](https://dl.acm.org/citation.cfm?id=735662) on processor verification. - ### Global Invariants ### In the verification of instructions, we do not assume the design starts from the initial states. This helps us to get a better guarantee of the instruction correctness when only bounded model checking is used. However, if there is no constraints on the starting state of a instruction, there @@ -144,7 +143,6 @@ Then in the refinement map ### Additional Assumptions ### - This section allows users to add additional assumptions in the verification. They can be, for example, * An assumption about the module I/O. From 34049c13734d37af89ee89f2a93461019dd84a85 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 9 Jun 2019 12:27:01 -0700 Subject: [PATCH 07/26] vtg --- verification/target.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/verification/target.md b/verification/target.md index df73bb2..782a085 100644 --- a/verification/target.md +++ b/verification/target.md @@ -1,2 +1,20 @@ # Verification Target +The verification target can be generated by create a `VerilogVerificationTargetGenerator` object. +Some prerequisites are: + + 1. ILAng should be configured to have the switch `ILANG_INSTALL_DEV` turned on. + 2. Include the header `ilang/vtarget-out/vtarget_gen.h` + +The arguments of the constructors are: + +1. A list of paths to search for Verilog include files +2. A list of Verilog design files +3. The Verilog top module +4. The variable mapping file (first part of refinement map) +5. The instruction start/ready conditions (second part of refinement map) +6. The output path of the verification targets +7. The ILA model +8. The choice backend (CoSA/JapserGold, the latter is not open-source and not included in the demo) +9. (Optional) Target generator configuration +10. (Optional) Verilog generator configuration From 3e6a7fdba9ea8ba26050e6713b7623202e699cda Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 9 Jun 2019 12:33:46 -0700 Subject: [PATCH 08/26] style fix - heading --- verification/refinement.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/verification/refinement.md b/verification/refinement.md index 76a31f4..50a5d32 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -11,7 +11,7 @@ Besides the above two parts, there are other auxiliary information needed. They * **interface signal information**: What does the interface of the Verilog top module look like and what do these signals mean to the tool. * **uninterpreted function mapping**: What an uninterpreted function inside the ILA model corresponds to. -### The Structure of Variable Mappings ### +### The Structure of Variable Mappings ```json { @@ -43,7 +43,7 @@ Besides the above two parts, there are other auxiliary information needed. They } ``` -### The Structure of Instruction Completion Conditions ### +### The Structure of Instruction Completion Conditions ```json { @@ -63,11 +63,11 @@ Besides the above two parts, there are other auxiliary information needed. They } ``` -### Module Naming ### +### Module Naming The module naming section comes first in the _var-map_ JSON file. It is a dictionary (map) with two elements. One element should have the key `ILA` and the value of it is what will be used as the instance name of the ILA module. The other element should have the key `VERILOG` with the value to be the instance name of the Verilog module. These names are used in all the expressions later when you want to refer to a variable in Verilog or ILA. -### Variable Mapping ### +### Variable Mapping The variable mapping in the JSON file is a map data structure. The keys of this map are the state variable names in the ILA model while the values are the Verilog variables. There are cases that one Verilog state variable can be mapped to multiple Verilog state variables and the mapping may be some special function. So the allowed value field of this map can be: @@ -93,7 +93,7 @@ Below are some of the examples: One note in the above example: the condition can refer to special signals (`__START__ ` and `__IEND__`), which are the condition when the instruction-under-verification starts to execute and finishes. -### Instruction Completion Condition ### +### Instruction Completion Condition The instruction completion condition is specified per instruction. In the JSON file, it is a list of maps. The list does not need to be a full list of instructions. Those not in the list will not be verified. Each dictionary must have an element whose key is `instruction` and the value of this element is the name of the instruction in the ILA model. Besides this name element, it must contain one of the `ready bound` or the `ready signal` element. The `ready bound` specifies a bound that the instruction takes. It is used for instructions that take a fixed number of cycles. Alternatively, one can provide a signal (or a predicate) in the `ready signal` field. @@ -105,12 +105,12 @@ The `max bound` can be used when `ready signal` field is provided. It provides a The `flush constraint`, `pre flush-end` and `post flush-end` signals are used when using the `flushing verification setting`. For this verification setting, you can refer to [our paper](https://arxiv.org/abs/1801.01114) on the ILA-based verification or the [Burch-Dill's approach](https://dl.acm.org/citation.cfm?id=735662) on processor verification. -### Global Invariants ### +### Global Invariants In the verification of instructions, we do not assume the design starts from the initial states. This helps us to get a better guarantee of the instruction correctness when only bounded model checking is used. However, if there is no constraints on the starting state of a instruction, there might be spurious bugs just because the design starts from a state that it will never reach when started from the reset state. In order to avoid this false positive, we use global invariants to constrain on the starting state. These invariants help rule out some unreachable states and the tool will generate a separate target to check whether the provided invariants are globally true or not. These invariants should be provided as a list of strings, where each string is a Verilog predicate. In the future, we will exploit invariant synthesis techniques to help synthesize these invariants. -### Interface Signal Information ### +### Interface Signal Information The Verilog module comes with a set of I/O signals and the tool needs to know how these signals should be connected. The `interface mapping` field is a map whose keys are the Verilog I/O signal names and whose values can be one of the following: @@ -122,7 +122,7 @@ The Verilog module comes with a set of I/O signals and the tool needs to know ho * `**CLOCK**` directive, indicating that this is the clock signal. * `**MEM**name.signal` directive, indicating this signal is the connection to an external/shared memory. The name part should be the ILA state variable name of the memory, and the signal part could be one of the following: `wdata`,`rdata`, `waddr`,`raddr`, `wen`, `ren`. If the signal does not directly correspond to the write/read data, write/read address, write/read enable signal, it should be specified as `**KEEP**`, you can specify the mapping using the additional assumptions. -### Uninterpreted Function Mapping ### +### Uninterpreted Function Mapping The ILA model may use uninterpreted functions, however, in the verification, the tool must know the correspondence of this uninterpreted function in order to reason about the correctness. In the `functions` field of the _var-map_ JSON, a map should be provided if uninterpreted function is used in the ILA model. The keys of the map are the function names, with the values in a list. Each element of this list is for one application of this function. Per each function application, the tool needs to know the correspondence of the arguments/result in the Verilog and when that happens, this is like a condition/mapping pair, and it is specified as a list. The correspondence of the function result goes first followed by the arguments (in the same order as the arguments in ILA function definitions). @@ -141,7 +141,7 @@ Then in the refinement map } ``` -### Additional Assumptions ### +### Additional Assumptions This section allows users to add additional assumptions in the verification. They can be, for example, From 8edd26bc17dc694b9f618ce0011cd150d7257e7b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 18 Jul 2019 12:24:56 -0400 Subject: [PATCH 09/26] update refinement map example --- verification/refinement.md | 48 +++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/verification/refinement.md b/verification/refinement.md index 50a5d32..c2d2443 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -91,6 +91,42 @@ Below are some of the examples: } ``` +The corresponding generated assumptions will be in the following form: +```verilog +wire __m10__ = Verilog_state_1 == __ILA_SO_ILA_state_1 ; +wire variable_map_assume___p1__ILA_state_1 = (~ __START__) || (__m10__) ; // __START__ --> Verilog_state_1 == __ILA_SO_ILA_state_1 + +wire __m12__ = Verilog_state_2 + Verilog_state_3 == ILA_state_2 ; +wire variable_map_assume___p3__ILA_state_2 = (~ __START__) || (__m12__) ; + +wire __m14__ = (~ __START__ ) || ( Verilog_state_3 == ILA_state_3 ) ; +wire variable_map_assume___p5__ILA_state_3 = (~ __START__) || (__m14__) ; + +wire __m16__ = (~ __START__ ) || ( Verilog_state_4 == ILA_state_4 ) ; +wire variable_map_assume___p7__ILA_state_4 = (~ __START__) || (__m16__) ; + +wire __m18__ = ( (~ __START__ ) || ( Verilog_state_5 == ILA_state_5 ) ) && ( ~( ~__START__ && __IEND__ ) || Verilog_state_6 == ILA_state_5 ) ; // __START__ --> match1 && (~__START__ && __IEND__) --> match2 +wire variable_map_assume___p9__ILA_state_5 = (~ __START__) || (__m18__) ; +``` + +and the assertions: +```verilog +wire __m0__ = Verilog_state_1 == __ILA_SO_ILA_state_1 ; +wire variable_map_assert___p1__ILA_state_1 = (~ __IEND__) || (__m0__) ; // IEND --> Verilog_state_1 == __ILA_SO_ILA_state_1 + +wire __m2__ = Verilog_state_2 + Verilog_state_3 == ILA_state_2 ; +wire variable_map_assert___p3__ILA_state_2 = (~ __IEND__) || (__m2__) ; + +wire __m4__ = (~ __START__ ) || ( Verilog_state_3 == ILA_state_3 ) ; +wire variable_map_assert___p5__ILA_state_3 = (~ __IEND__) || (__m4__) ; + +wire __m6__ = (~ __START__ ) || ( Verilog_state_4 == ILA_state_4 ) ; +wire variable_map_assert___p7__ILA_state_4 = (~ __IEND__) || (__m6__) ; + +wire __m8__ = ( (~ __START__ ) || ( Verilog_state_5 == ILA_state_5 ) ) && ( ~( ~__START__ && __IEND__ ) || Verilog_state_6 == ILA_state_5 ) ; // __START__ --> match1 && (~__START__ && __IEND__) --> match2 +wire variable_map_assert___p9__ILA_state_5 = (~ __IEND__) || (__m8__) ; +``` + One note in the above example: the condition can refer to special signals (`__START__ ` and `__IEND__`), which are the condition when the instruction-under-verification starts to execute and finishes. ### Instruction Completion Condition @@ -115,13 +151,23 @@ might be spurious bugs just because the design starts from a state that it will The Verilog module comes with a set of I/O signals and the tool needs to know how these signals should be connected. The `interface mapping` field is a map whose keys are the Verilog I/O signal names and whose values can be one of the following: * An ILA input name. This means that the Verilog input signal corresponds to one ILA input. They must have the same encoding and bit-width. - * `**KEEP**` directive. Telling the tool to have a wire of the same name and to connect it as the verification wrapper I/O. + * `**KEEP**` directive. Telling the tool to create a new wire and connect it as the verification wrapper I/O. * `**NC**` directive, indicating that this port does not need to be connected. * `**SO**` directive, indicating that this is actually a direct output from a visible state variable (a state variable that is modeled in the ILA). * `**RESET**` or `**NRESET**` directive. Indicating that this signal is the reset signal, active-high or active-low (we assume synchronous reset). * `**CLOCK**` directive, indicating that this is the clock signal. * `**MEM**name.signal` directive, indicating this signal is the connection to an external/shared memory. The name part should be the ILA state variable name of the memory, and the signal part could be one of the following: `wdata`,`rdata`, `waddr`,`raddr`, `wen`, `ren`. If the signal does not directly correspond to the write/read data, write/read address, write/read enable signal, it should be specified as `**KEEP**`, you can specify the mapping using the additional assumptions. +For example, for a Verilog input signal `control`, the effects of applying different directives are: + + * An ILA input name, e.g., `c1`. The tool will check if ILA indeed has the input `c1` and the type is matched. The wire `__ILA_I_c1` will be created and will be connected to the input port `control`. + * `**KEEP**` directive. The tool will check if the signal is input or output and create an input/output wire named `__VLG_I_control` with the proper width and connect to the port. + * `**NC**` directive. The tool will have it unconnected like `.control()`. + * `**SO**` directive. The tool will check if it is indeed an output and create an output wire `__VLG_SO_control` and connect to the port. In this example, because it is actually an input, the tool will give warning. + * `**RESET**` or `**NRESET**`. It will be connected as `.control(rst)` or `.control(~rst)`, where `rst` is the reset signal of the wrapper. + * `**CLOCK**` directive. It will be connected as `.control(clk)`, where `clk` is the clock signal of the wrapper. + * `**MEM**name.signal`. The tool will check if `name` is an ILA memory name. It will be connected as `.control(__MEM_name_0_signal)`. + ### Uninterpreted Function Mapping The ILA model may use uninterpreted functions, however, in the verification, the tool must know the correspondence of this uninterpreted function in order to reason about the correctness. In the `functions` field of the _var-map_ JSON, a map should be provided if uninterpreted function is used in the ILA model. The keys of the map are the function names, with the values in a list. Each element of this list is for one application of this function. Per each function application, the tool needs to know the correspondence of the arguments/result in the Verilog and when that happens, this is like a condition/mapping pair, and it is specified as a list. The correspondence of the function result goes first followed by the arguments (in the same order as the arguments in ILA function definitions). From 31d14c1e2be1577ace69b335de10499dc8229c7e Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 6 Aug 2019 23:00:07 -0700 Subject: [PATCH 10/26] add explanation for annotation --- verification/refinement.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/verification/refinement.md b/verification/refinement.md index fbe78ad..083a046 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -37,6 +37,11 @@ Besides the above two parts, there are other auxiliary information needed. They // more ... ] ] + }, + "annotation":{ + "memory": { + "":"external/internal" + } } } ``` @@ -166,6 +171,20 @@ For example, for a Verilog input signal `control`, the effects of applying diffe * `**CLOCK**` directive. It will be connected as `.control(clk)`, where `clk` is the clock signal of the wrapper. * `**MEM**name.signal`. The tool will check if `name` is an ILA memory name. It will be connected as `.control(__MEM_name_0_signal)`. +## Notes on Memory State Variable + +Memory state variable might be internal or external to the module. An internal memory variable corresponds to a verilog array, and therefore no specific I/O interface is needed to access the memory. An external memory is a memory that connects with the current module via I/O interface. By default, all memory variables in the ILA are treated as external memory. The default setting can be override by _annotation_ in refinement map, and here is an example: +```json + "annotation" : { + "memory" : { + "rf":"internal", + "mem":"external" + } + } +``` + +The above annotation specifies memory named as `rf` and `mem` as internal and external respectively. Being internal or external affects how properties are generated. The mapping of internal memory is element-wise with expressions comparing two verilog arrays entry by entry, which is inefficient for a large memory. The mapping of external memory will use memory abstraction, which is more efficient. + ## Uninterpreted Function Mapping The ILA model may use uninterpreted functions, however, in the verification, the tool must know the correspondence of this uninterpreted function in order to reason about the correctness. In the `functions` field of the _var-map_ JSON, a map should be provided if uninterpreted function is used in the ILA model. The keys of the map are the function names, with the values in a list. Each element of this list is for one application of this function. Per each function application, the tool needs to know the correspondence of the arguments/result in the Verilog and when that happens, this is like a condition/mapping pair, and it is specified as a list. The correspondence of the function result goes first followed by the arguments \(in the same order as the arguments in ILA function definitions\). From 3d050930a5e08ea22515fedfd41bf94224ee75f2 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 8 Mar 2020 22:06:27 -0400 Subject: [PATCH 11/26] add descriptions for monitor/value-holder --- verification/refinement.md | 137 +++++++++++++++++++++++++++++++++---- 1 file changed, 122 insertions(+), 15 deletions(-) diff --git a/verification/refinement.md b/verification/refinement.md index da1699c..ba6726c 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -91,7 +91,8 @@ Below are some of the examples: ``` The corresponding generated assumptions will be in the following form: -```verilog + +```text wire __m10__ = Verilog_state_1 == __ILA_SO_ILA_state_1 ; wire variable_map_assume___p1__ILA_state_1 = (~ __START__) || (__m10__) ; // __START__ --> Verilog_state_1 == __ILA_SO_ILA_state_1 @@ -109,7 +110,8 @@ wire variable_map_assume___p9__ILA_state_5 = (~ __START__) || (__m18__) ; ``` and the assertions: -```verilog + +```text wire __m0__ = Verilog_state_1 == __ILA_SO_ILA_state_1 ; wire variable_map_assert___p1__ILA_state_1 = (~ __IEND__) || (__m0__) ; // IEND --> Verilog_state_1 == __ILA_SO_ILA_state_1 @@ -158,18 +160,19 @@ The Verilog module comes with a set of I/O signals and the tool needs to know ho For example, for a Verilog input signal `control`, the effects of applying different directives are: - * An ILA input name, e.g., `c1`. The tool will check if ILA indeed has the input `c1` and the type is matched. The wire `__ILA_I_c1` will be created and will be connected to the input port `control`. - * `**KEEP**` directive. The tool will check if the signal is input or output and create an input/output wire named `__VLG_I_control` with the proper width and connect to the port. - * `**NC**` directive. The tool will have it unconnected like `.control()`. - * `**SO**` directive. The tool will check if it is indeed an output and create an output wire `__VLG_SO_control` and connect to the port. In this example, because it is actually an input, the tool will give warning. - * `**RESET**` or `**NRESET**`. It will be connected as `.control(rst)` or `.control(~rst)`, where `rst` is the reset signal of the wrapper. - * `**CLOCK**` directive. It will be connected as `.control(clk)`, where `clk` is the clock signal of the wrapper. - * `**MEM**name.signal`. The tool will check if `name` is an ILA memory name. It will be connected as `.control(__MEM_name_0_signal)`. +* An ILA input name, e.g., `c1`. The tool will check if ILA indeed has the input `c1` and the type is matched. The wire `__ILA_I_c1` will be created and will be connected to the input port `control`. +* `**KEEP**` directive. The tool will check if the signal is input or output and create an input/output wire named `__VLG_I_control` with the proper width and connect to the port. +* `**NC**` directive. The tool will have it unconnected like `.control()`. +* `**SO**` directive. The tool will check if it is indeed an output and create an output wire `__VLG_SO_control` and connect to the port. In this example, because it is actually an input, the tool will give warning. +* `**RESET**` or `**NRESET**`. It will be connected as `.control(rst)` or `.control(~rst)`, where `rst` is the reset signal of the wrapper. +* `**CLOCK**` directive. It will be connected as `.control(clk)`, where `clk` is the clock signal of the wrapper. +* `**MEM**name.signal`. The tool will check if `name` is an ILA memory name. It will be connected as `.control(__MEM_name_0_signal)`. ## Notes on Memory State Variable Memory state variable might be internal or external to the module. An internal memory variable corresponds to a verilog array, and therefore no specific I/O interface is needed to access the memory. An external memory is a memory that connects with the current module via I/O interface. By default, all memory variables in the ILA are treated as external memory. The default setting can be override by _annotation_ in refinement map, and here is an example: -```json + +```javascript "annotation" : { "memory" : { "rf":"internal", @@ -203,12 +206,13 @@ Then in the refinement map } ``` -## Additional Assumptions - -This section allows users to add additional assumptions in the verification. They can be, for example: +## Additional Mapping -* An assumption about the module I/O. -* A mapping from the Verilog design's memory interface to the provided 6-signal memory interface. The AES case study provides an example of this. The Verilog design uses two signals `stb` and `wr` to indicate memory read and write enable, which are different from the `ren` and `wen` signals. Therefore a mapping is provided as follows: +Sometimes, the mapping between Verilog variables and ILA state variables does not fit easily into the +state mapping section. For example, you may need a customized mapping from the Verilog design's memory +interface to the provided 6-signal memory interface. The AES case study provides an example of this. +The Verilog design uses two signals `stb` and `wr` to indicate memory read and write enable, which are +different from the `ren` and `wen` signals. Therefore a mapping can be provided as follows: ```javascript "mapping control" : [ @@ -217,3 +221,106 @@ This section allows users to add additional assumptions in the verification. The ] ``` +Assumptions in the `mapping control` section does not appear in the invariant or invariant synthesis +target. + +## Additional Assumptions + +This section allows users to add additional assumptions in the verification. They can be, for example, +an assumption about the module I/O. + +```javascript +"assumptions" : [ + // the two inputs can not be both 1 + "! ( verilog_module.input1 & verilog_module.input2 )" +] +``` + +Assumptions in this section are in effect when verifying the instructions, the invariants and when +synthesizing the invariants. + +## Value Holder + +Value holder (a.k.a prophecy variables, auxiliary variables and etc.) can be introduced to capture +the value of a Verilog variable at a certain time (or under a certain condition). +Below is an example of a value holder: + +```javascript +"value-holder": { + "r1_pvholder" : { + "cond": "m1.write_enable == 1", + "val":"m1.registers[1]", + "width":8 + } +} +``` + +The above value holder will be translated to the following Verilog code fragments in the Verilog. + +```text +input [7:0] __r1_pvholder_init__; +output reg [7:0] r1_pvholder; + +always @(posedge clk) begin + if(rst) begin + r1_pvholder <= __r1_pvholder_init__; + end + else if(1) begin + r1_pvholder <= r1_pvholder; + end +end + +assume property ((m1.write_enable == 1) |-> ((r1_pvholder) == (m1.registers[1]))); +``` +It creates an auxiliary Verilog variable `r1_pvholder` which carries a undetermined +value. +Its value keeps the same all the time, and an assumption says this undetermined +value is same as the specified value `m1.registers[1]`, under the condition that +`m1.write_enable == 1`. +This variables can be referenced in other sections by `#r1_pvholder#` (this tells the +tool not to find this signal name in the original Verilog design. +The `width` part can also be a string `"auto"`, which +tells the tool to automatically determine the width (in case of failure, error will +be prompted.) +This value holder does not check if there is only one cycle that `m1.write_enable == 1` +holds. If there are multiple cycles that its condition holds, the assumption may +overconstrain if `m1.registers[1]` should carry different values at these points. +This situation should be avoided. + + +## Verilog Monitor + +In the case that user may want to add customized auxiliary variables, we support +inline monitors for this purpose. + +An example is given as follows: + + +```javascript + "verilog-inline-monitors" : { + "stage_tracker" : { + "verilog": + ["always @(posedge clk) begin", + " if (__START__) stage_tracker <= 0;", + " else if (__STARTED__ && !__ENDED__) stage_tracker <= stage_tracker + 1;", + "end"], + "defs" :[ ["stage_tracker", 2, "reg"] ], + "refs" :[] + }, + } +``` + +This creates a 2-bit variable `stage_tracker` to track the number of cycles (this is just for demoing +the syntax of Verilog monitor, you can in fact use the embedded variable `__CYCLE_CNT__` +to track the number of cycles). Variables that should be accessible outside the monitor +should be defined in the `defs` list with its name, bit-width and its type: `reg` or `wire`. +Variables used only inside the monitor can be defined inside the `verilog` code list. +Any variable inside the original Verilog, if referenced, should be put in the list of `refs`. +This will help our tool to add auxiliary wires to connect them with the monitor. + +Value holders and monitors are normally only in effect when verifying instructions. If you +want a monitor to appear also when verifying the invariants, you can add the `"keep-for-invariants":true` +attribute in the monitor's description following the `defs` and `refs` attributes. + + + From 70b278f43445e247c050a25c777f7feaec7d9be2 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 8 Mar 2020 22:15:06 -0400 Subject: [PATCH 12/26] style fix --- verification/refinement.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/verification/refinement.md b/verification/refinement.md index ba6726c..caeae12 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -287,7 +287,6 @@ holds. If there are multiple cycles that its condition holds, the assumption may overconstrain if `m1.registers[1]` should carry different values at these points. This situation should be avoided. - ## Verilog Monitor In the case that user may want to add customized auxiliary variables, we support @@ -295,7 +294,6 @@ inline monitors for this purpose. An example is given as follows: - ```javascript "verilog-inline-monitors" : { "stage_tracker" : { @@ -321,6 +319,3 @@ This will help our tool to add auxiliary wires to connect them with the monitor. Value holders and monitors are normally only in effect when verifying instructions. If you want a monitor to appear also when verifying the invariants, you can add the `"keep-for-invariants":true` attribute in the monitor's description following the `defs` and `refs` attributes. - - - From f3b3401b9aa31079992a0cb57fb05cf6c774da6c Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 29 Oct 2020 15:44:29 -0400 Subject: [PATCH 13/26] verif readme --- verification/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/verification/README.md b/verification/README.md index 4a007cf..c3aa344 100644 --- a/verification/README.md +++ b/verification/README.md @@ -1,2 +1,16 @@ # Verification +This Chapter explains how to use the verification functionality +of ILAng to generate verification target to work with existing +model checkers. Currently we support Cadence JasperGold, CoSA, CoSA2. +For other Verilog model checker, we can generate a standalone +Verilog with embedded assumptions and assertions using the +SVA format. + + +For verification, you will need (1) a ILA model (2) the Verilog +module (3) the refinement relation to map ILA and Verilog, +this is shown in the following figure. + + +![](.gitbook/assets/rtl-verify-arch.png) From 2caf8bb0da1bd7469569d9b20e84958cea7a7ed5 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Thu, 29 Oct 2020 21:52:17 -0400 Subject: [PATCH 14/26] cond map sec1 --- verification/example.md | 78 ++++++++++++++++++++++++++++++++++++++ verification/refinement.md | 2 +- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 verification/example.md diff --git a/verification/example.md b/verification/example.md new file mode 100644 index 0000000..0c254df --- /dev/null +++ b/verification/example.md @@ -0,0 +1,78 @@ +# Examples of Refinement Relation + +Here we'd like to give some examples of the refinement relations. +The features described may include some of the syntactic sugar we are currently working on, +which will be marked in the text. + +## Conditional Mapping + +In variable mapping section, the conditional mapping is helpful in many cases. Below we give some +examples using conditional mapping. + +### Mapping Loop Body with Unrolled Pipelines + +Suppose we have a specification for AES-128 function, which consist of 10 rounds of cryptographic operations, each round takes results from previous round and generate new ciphertext and new round key which will be used in the next round. +In the ILA model, this is described with the help of child-instructions that form a loop. +Whereas, the implementation is a pipeline which corresponds to an unrolling of the loop in the specification. +This is illustrated in the figure below. + +![](.gitbook/assets/aes-128-loop.png) + +When verifying the child-instructions, we need to map the state variables holding intermediate results \(suppose it is named as `ciphertext` in ILA\) with signals in Verilog. +However, because the loop is unrolled into a 10-stage pipeline, the corresponding Verilog signal for `ciphertext` is dependent on the round. Therefore, we need conditional mapping here, which can be specified as follows. + + +```javascript + "state mapping": { + "ciphertext" : [["ILA.round == 0", "s_in" ], + ["ILA.round == 1", "s0" ], + ["ILA.round == 2", "s1" ], + ... + ] + } +``` + +Or, alternatively, you can use: + +```javascript + "state mapping": { + "ciphertext" : [{"cond":"ILA.round == 0", "map":"s_in" }, + {"cond":"ILA.round == 1", "map":"s0" }, + {"cond":"ILA.round == 2", "map":"s1" }, + ... + ] + } +``` + +Regarding the `round` variable in ILA, because the loop in Verilog is fully unrolled and the effects of `round` already appear in the mapping of `ciphertext`, we don't need a mapping for it. We can simply write: + +```javascript + "state mapping": { + "round" : null, + ... + } +``` + + +{% hint style="tip" %} +The condition specified the first has the highest priority. You can have a default case with condition `1'b1`. +{% endhint %} + + +### Mapping State Variables with On-the-Fly Values + +When tackling pipelines, it is also + + + + + +{% hint style="working" %} +The syntactic sugar `signal@condition` is a feature we are working on and is yet to be merged into the main branch. +{% endhint %} + + + +% stage tracker +% delay monitor +% @ time (condition) diff --git a/verification/refinement.md b/verification/refinement.md index 107c6c4..0ef1cf2 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -181,7 +181,7 @@ Memory state variable might be internal or external to the module. An internal m } ``` -The above annotation specifies memory named as `rf` and `mem` as internal and external respectively. Being internal or external affects how properties are generated. The mapping of internal memory is element-wise with expressions comparing two verilog arrays entry by entry, which is inefficient for a large memory. The mapping of external memory will use memory abstraction, which is more efficient. +The above annotation specifies memory named as `rf` and `mem` as internal and external respectively. Being internal or external affects how properties are generated. The mapping of internal memory is element-wise with expressions comparing two verilog arrays entry by entry, which is inefficient for a large memory. The mapping of external memory will use memory abstraction, which is more efficient. (In the future, we will support mapping internal memory using the Array data-type of the underlying property verifier.) ## Uninterpreted Function Mapping From f6ed4aee50e4c7e59d4f2490e858dad7a5840a42 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Sun, 1 Nov 2020 21:38:40 -0500 Subject: [PATCH 15/26] Add Examples --- .gitbook/assets/aes-128-loop.png | Bin 0 -> 18163 bytes .gitbook/assets/future-values.png | Bin 0 -> 43378 bytes .gitbook/assets/simplepipe.png | Bin 0 -> 25923 bytes verification/example.md | 211 +++++++++++++++++++++++++++++- 4 files changed, 204 insertions(+), 7 deletions(-) create mode 100644 .gitbook/assets/aes-128-loop.png create mode 100644 .gitbook/assets/future-values.png create mode 100644 .gitbook/assets/simplepipe.png diff --git a/.gitbook/assets/aes-128-loop.png b/.gitbook/assets/aes-128-loop.png new file mode 100644 index 0000000000000000000000000000000000000000..18e0192020885eef308015793a753a0d728f3126 GIT binary patch literal 18163 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

7cf!KY7Mi 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

-M@m2S*Ph=B5mD` zRIhgRw+l9=Fc ztNCO`B!taiZs+IFFO2siBnFt+fD3c$?;DNT&zfnRMBG`4ky9Z6**TuP=}W2eQ*JEw zc-5VE9sWtU2|D*TRSQYVupgh8-)>Bvyn)(mo2=XZa}Q%#>2MelbHQA#)i7QiZxsJOIO&AyGcHHNI3L1OiMGFofV08-Mx=xA3HCGv6I!y3wW%YPd! zsn!mmG3Q^@R%!W~7mRSET@6xC!wZtv<}hUoz?5)>Cf6;PFYlaEHtI*tJNqkOrf_@2 z*8tumozxRGN}}*Ut};*x$gM#trjcpOw@o~qt;_F4g7@v|*I)ae%9*uBJ;}H(-w`1nIKV+zDVRO)?cY-)FO)F54)9`IRbj%6MP5_2e(vsap z59EQe-VlxXeY%{~vxk%1?8lwzic+tfa6t+lBDF zQkMSFAG!!70k(|tS{(H7+P#`jNa0ut#M~vUxcPV&3@uw6>U({K%VhW zWyX+_jyo~Sq-YUZ-V-FjR>{Uy)f1YApf}0jVp5N|D)O_Um)k1tO_mIXIs4gTa1KuT zYj{fj|;<|lTyTb$nV37>e~z{tD>iWq>bfgmQ6&q zpFV1~2|w?UhWHH*VXXDF4q2pt;bh2*ooSfmOCa%Jt;Zs$;-N@68UGr$+p$GFwH#2J zi8Xea1tH5mnHm=GEG7B{9+U~Vcue|#9*O~tX7+*9ZTyQqdiFRs3GDd5Fx$Pr-KW&@ z4J~3*xMKR_LrrlvXGIbLYDrFEWZKl_Gx+TR5;wYv(iU{K*5do zhsy%JfaImyb)V22nH%$GV^&Z`u(_8=WbPgR#(M+ zu|y$+_NO570*Ex;g~*SW|zIs?(psBzFNCNZ?6o0}Q!jgQnYLRVR>_7<1`24D58pMi7mQA z%>G}!)V-n&Jx>D>3iz+~KGX6p9E3htWH}OspSYN zr9wYK02*}Kk0w}vI%yU+hyh@oE_zT~!Fb*fSyDcg`g!GMnH5a0Z2 Date: Mon, 2 Nov 2020 10:02:50 -0500 Subject: [PATCH 16/26] update figure --- .gitbook/assets/rtl-verify-arch.png | Bin 0 -> 85906 bytes verification/README.md | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 .gitbook/assets/rtl-verify-arch.png diff --git a/.gitbook/assets/rtl-verify-arch.png b/.gitbook/assets/rtl-verify-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..d8b0afe6fe96320e87d4ba787dc52d172ced2469 GIT binary patch literal 85906 zcmeFZcQ}>*A3shUyX=|0WlOTRIA)!)|lt01x;d zAH7G?z(3gT5Orm&!cUBgzz?{0m2{M_uu7td5AOg^ViDfgFm}hnq9w@Z_5YQ&sjo_eQJAUP@ht&3e6_W z^p9lId-qzjN2FfqzF3tn+nK*LA?uQ?vI z|3hk^`AxF0SL&us=XF^XUB_*boP&|y&O9;jsBJR7^|w=mk| ze%l^0@1hGW#6l*?FhXH#0^H|=ZFgU$$My=zFH0IQ`AOuY^UOS=$R(PIyF>T**H`ir zRaHWb+S|9Z2xG2o-oD5_KcJzS8xTa0u-A>SCA0Vb)*;q#+)p}1ymU!JNwu+v&hYm~ zfisfFgRscyGYvzHKlk$%BzM+Q#4bW-LI%FFZ8q}2bUA(I?+jBvo(MDNTX=N|BBDDk zc1AqeQRYVo&V%i@!dTO^v=b896gR(FP^Z@$CT$O_am|@LThQu2!4~gB-m-&sP}g@w zZT?VAmpd0bq!3{3grr$_BIDe3X9?Yg)c_Lx_>qTxrq0yeCwubH2&8IYMX5 zQrmj&O)jhE<|4JG32Pf6mEfafH}!9M)kEpVLRUr*7Yvom^}$4&zHNUcuFdut;eCye zT<{#ZaRJo>zBdWcamwsht<#Nkc=JB@H43M#%dG0~>^&Zs+Ntj0Q@eL>@zLgM9w&=Q zvTWD9sqEhVs|jjM4NrvL2ut&ZO4!I^N0C}lRMiSCf8kQwWqGis01J2R=W0b>P86r{ z?ogDE@4s8$fjnwOWpY^A?#LBTsRqos^Umk!+-6U=1?B9dl=P+RGi~d2s}?L-{}st& zaHRPVHJ7jI>#)Gs$sjK0a_ex4TkHm`Qst@?*3d9#;R|N!>Lcm_us2yjk>PQI{^=E+ zn;SU^x)2t{B>#QStoG(7Nigu9f9nsG?sh_v1HUP{{9gS2MY=FXm5aPq4YbleQ2%}n zrLd9eJ=3uGjA38uQ0i@!%Dah8XVfY}oM{uy<*NEPOysj$OD!~m;364Uv}*qXZ1&3F zqg(wDoorI`4lfNxY)jRm+S2UEB>7T>K_xTC7EwF<5T{{DBiJ>C8!RgsE+&jzgf{}E z#jbtfK?*xfH4X3E(AQ-zlqellPd&_b94wip%htZFAkBm`*z8qr2%%A!_54X|m6f&k zgU6m^+bd(z{gAe4d1d&)xenH`&sPT%7iJTkZitD$DLPB<8xA;VUm3?uxiY-758gtd zz;3~6pP9*ZzS!D)bOD`VreKndwJoKK#LiRjk>QM@k)dc1Uf%y)=on4m;Pati$X6}u zh5uT??B|WPBx;yn5~Io!I-Cg?3)ltE?c{^cYbji#>+;>Z;vFHqk69Rl9jiEB6|!*Q zazQ>J^Dm#FBwIH%Fm~up<3f!7y~h21{H;ql_$afZnK zSl8lggHibi4Uoxb4s~u=lDYpAMwy0mame)|yR8lg3p7EI{~k%{uFTpGm4Hw2yIBe- zf0@#N!;vTEj}}LEIOa1)EzjC2Q$sgcOFq^b{X|?)aa$sm*Ok95M%I$}NE!8-|EP35 zUX7@Ihuw$D9+u?OsHp2s=y<~_ref07ie|^3&A46KIp+=9 z{|?EKU2Lj{EacN9{#mF0Zuc@com@~$po?Q{`;u~vxcFk+r+iDTqA!~7^-{MtC`XFQ zVNs*${&Ip~1nGlk`EKW9hq4p{gysN`hDR_2i)kvUc4wwVnG=Ssg)v|Cn^bk{c>03# z9?MzzrDPcfhWAl!P*g1G^{}Z{u~~{=_#K2wiOtC9XHz%SK)F;mf z@Q!p80anTr{ZNJ?pIBkukfLpyrKTa2y=GV6&vy!kivLs9}^>cse9og zvRz_c;Lot9b@e;pX++00hxVUt!+temGNUhj5Kg7N92i#*@e|J)c?{yQUD?clFfVRinjyUY8)@>;L zne5`Grqx)^pRKyC7}C`X-o!n5Q^NiJyutk4at-XH_2ATgvEI0=wY_8}!_^Co8TBlJ zW%>RKio7QM`5Jt$C%44cp10Dz-gHk;9Oknm@!f4Bgfx@!yzJvKq@&1xwH&W3b0OB@=qRB?HdP29ys zsb74z7IEbQnX(UbpWaP<6pQR;sW21*Sfr3ncERh}s3*t9*ywHzeziz!^LQk0dP23R z3hZlAxp3efz1xMIb?8x}dY5HG086KxV`x~%T~Q(9=;wdaGaa|SUkUYt8o^9Mp&-t1 zUcevyS)Xm+6J&85;Jsl`qhwWp*CXa-A6F%p zFOcAa)sZ0aB1%a(hjoS}4>V^xsHqGMX(!*Kk3^-OjX-l3aKmZt$N0N$*r<oUg}=&Tlnzpxyy1cHtH?>6MNt5vKbhJ7|oXz!@{DH;4dh4stV~X6ML0!t^1qK55RlD zx7MXfm$K(eVqRN3*XI$GTz!psTBwz%(ZS$AV5%%5%kUy{s-ao(rNZmbUWG>J!b#M+ z#eezfN78qf*vUbA!oK?J4bj5q{cBfKr+z>iW%uU?uQUrcmPmZr*Q3Q(Xk0Cys{66R zJnsI*Ys+%Fc@}z6_NZnn7&-~#V9O3UTq<0K2cVYh*0(?Yz>hAHmVLMoEaOZO%odL# zd9j>}gJH8w(NSqX{ID$KTn5!`lAI}JUJ&ho79VdOLDMSwIn6ftBtBXXgZgq0Qy9(N zzSob-YFDvB=H;y8M$V>Py_D`AKZFG;Pb0nD% zY4{=0>v0nYh{^GSF*c33@WEyWGTfLzUYrg6y&=_lKS`--;dI7}!a9Ny)ps)@1y}9E zCU=hTMRy*8gptCuek|9~d4=4Q^wI*quF-X3Cv}g0cu+(GcXXpBtpU|~Q zzsNjlAb=!$q%bnqLPD?%NR4M$&reG2$pNwnFCk5~Az+)wJ?5}DY7Q7jUmz8(iMEWn zL&tsd{`+XHU>ki_G_jOOCxQY(lp7)IJzAU2G+=D)82>I#KKQ#@@BDOjzKqE<0-v_m`?_MV22jq_hx?;9b&O*ktwH@e>*@TKkkq#H${JG5 zPUmcQCu?_(UI4^3>reu5RojF0(2qWBNcnb7JbJMd%!ho_WJ7F_-!MSuadf=0_)q))Ry1&N` zIG3}tWzRsu#HmnW{}I4zNxOgw0Ur-p@G_}=5#5{|9v~$Oj=jG4#Gv{Bx)u>wI2#VF zh^#b9$uI%qd;ZH+xeO`~rdy9odM-%JEAo7Jfqo$PX1%jxSG`xQd|>i*D&id-^Yc>1`9ffnz0z&8KKm5>;>tv>t*9(f?d&)Hm3 z;O!WzukNIL;tK7LV!m$O)g;M~b@AK$TTC4joUjr~h!X;BCxIdtJYh8g!q$-2a;KKJOTxbg8ilDtHTe`>eJZzdtT|;PXvn)lcueY0QzmY((}=akZm3`>FXEpia|xM`s5X4!LN#E z`{h%M)#b_FQDBFVof{V?r~Po57k}OTdvd=pNUJE>_k{x-kQaT3_SGam5D!wJW<&cX zt{roOUHa7OUelNGpu@v0F8t&b3=c)CwYrThO|An#!27^@ZS|m{bjMUxfEo11G7^6g;(JfR5Ld5kiXm52@SW;mJnK~{!qM(lxP%7M?h z`Xj_UBhDV-#D&-dGLh4mD90P~02^#aK$ zk_xl~J!1&c*?ubrDCSjVrb73Q^@66kNKYl!$4-j%P7Y*c6^^A$fbINDgR&;TzA(V| zN@22-QNM6_`@&EC6V7s1!Ex}iSB*Jb=W?TuO>b`7C>apR!?rp;z{mkVTa|gTwl=rk zM?10IEJAWwqgj(FHPtGS)nL7~{g)zQxsfk9YE}im&^0wk2-F^bd#ld zbcy7pT$O!o`htW>Yzt*us9b)Nf=Nj0Z`21Gi-0Zt-i z-?eXI2~Cw!!WU;p5lq4A!sBC(2r`Inni0(U{@zPrj5DiOK6Jdd7{@f>f$@je-U7Hh zn{Qk;U4Hr5f)+!TyP?shFopc1WZ?X7fOj=jyIY!*X)|qSS|AUD;VIvZiPff_T@GH1 zUS-i{`C&j46f0=z)_gCX3?g*DsW+hU;qesOrf77V$(aP^ePnLxw317Nv8xL?tZdmL za+6w|+JJuE~sW(&w*Pr!sT~bATRo7&0*f=a1k52&6)holN=dr@q$Gj z=`kVYP%=~2SPOdX0&W0;+IY?0cNv>IZ$-Cr7jt^O7aKy+(`Dlx?*Nx$WlVdw(KX4hUP0ut>uX9Do~_dsSFrs4+0#+KCZ_-)X3^nVWBbJxdY zOzB6En3yGHJ`4tlzfMG}8@RseeG zDf4L%@R3~AvDSGBxxctnGb?yN+qLl1sqhkpz*oRI5Hns7aK2C6hpYQls#t6xSihdO z-f5{z-V}xdQT*n=J>E_KI}s04T>|a7d~$Z`YBIXkRQELR6CkfaE`Xa`w3H4#~fJ>65KXaQn+Ba{FK(8he^?~vd?gn$F^D4=u>DqhA@^A`A} zwi&>UhUZHvpdZM0_jevOzFAGhNDtf3syvLa@K|N|znrP1epg)^kik!;Q=SlKMXs^F)Vd< zF8p*M0p6cxRc2a!!WGkBt`@<6EN1Zum1E>bIp?k>UIs(iecID=L(fqA_uN``kovVB zxqxch))%V0JWuT<GgKwWc~e0XG2beIQ1aSU6zbtTWyz+;TR2t5OL@(IYU4Oz2Eb6n;X=g2Bc7nz50mc6R| zclK4gv!gI4eTI-JsC=;Z^66OJ8UqQgVc{|_U3!Vp5E8)4Zt4# zi@I;8K16oLhu9(9o`AJ=YccQNiK=CO)N9TyLiZ4%FX5Co_Rb9rK$o?=WMVh#kxqdsy?rMS@bh7a+%S$&bW zH`XuY9!6w{O8BP#A#L9J$B0YQ6id)umI{v>^bJgYp4<6qHvL%B3soRiqJqtA*cV~-eqU|)g~WP{G?*-$sxqkZd8U0+cs8W~gGf(>J>ojfw2S;C|MR5g z@Fd8wkXp>48h8J3Rp6dhXB{$T8}B5Rq^Y8Xa!)J-%nzDu=vCU9M^8zq_#s8Q)b`E4 zhx=V1`q=;3rSS_UBDQ}=fBmh^X19KRzWw#u9-4}*W}6QNa*zwBVUOaVE?F9YIP+X! zqBK~WC$Z2)JRWGV&y5;M53@gtl8xOl~kHuCmN0i z^hSBWNcAjBeq&;?3KKSu7te_E5!JRZll(TUuF`xj-A|w>ep3lU>CI0V1EUoLZCn;& z!)pm;uA6FR$0{<$99;a5gPBdyYO`-K^UqWLoE(@$9rUm|%pYb~c31eVRyX!Z){#1~ zsJK?Et#c)qpj?ljlqIK9deTI-qs%=9YB!XaeuX-h$@$4~AseoP@NrIb^oLyps z@)Gtx^f_J93S}&0z~n(7tR}@fYbhN!2B9?-4-2b;d0ZTXcvX<3XZQhTLK%j{Gv>ht zDZJUt|2L8b5%}s8m&uBjcL9fN7f?sypC;tec#c!IFyWJQT|Od4J0;A2gV&~2Ou!+< zY5zq`S93A~7T42cnwkZEK$RKwqqa$Zy93Q1cL)-y8<6q3`tKelo3tO%a?%@EBGUvM zL5FVvDxC^4SH3Ou+XrNR`9K7f>;Zge%Ldzk)MVbzgXw<@OjGH&bV^_yF!~cy8i?Hnzt7zQ51Ec*^^d(r@ zWCe4^efuMgcNl4$AgToJe<~qPov1yi=P~eEXz9n{h|%(QH$y$;0F^NRldzN8w7>PA zFMW~(f4v5kj(kOiax$^7$tc8sNa!k+fx$(K;JGy@CTE<~{hE~jbd?QI+Rh*}00d<; z;(FaPD>jp@6$&DFmyckI|EBmmZZ-WEqW>LK{*$Ty_upHeM;DAF2CNyM4GO=Zpd8_^ zLL~M|%8!@j|8Ukbpp|F#cYTTh**Q@ z{0AU&T2DKO^{Uwa!U zPyR2EI)ju?(6IK#-}>MrFrHXL{s{oS^8|=ZY(qd%0K7c)x0zX=$3&Ua%HtQLmh1BU zpVR`t|NljX;O_u{9AsDq(BzdWN(laFnd*1zw9x+cvnKi*r7wcT(j!gTGwcisP>;9y zjVfo@%e04LX1zaNoV@4EvtuzcjQRmu*IoNEA#n5V``J&F2mVydXKnTmi#%O^V$R`# zna18bv^mgbwvGako?GXom^GVyvJ~pxT>?IC^@)_`aNdxzc^lVtVQ&kKGW-@#^W)|I^Ao zx?UbhmmsK)=C4FFQnIH2BuAU?A2B=aiAZs}MSuK-t>sWm(%G#2?$H(6^6rBol~SaW zeo!r=I)Jl&#f0lXOvtd~1%VlWw5u*D5A>3#40J}c9)>v&EXy5n*)>)Tcd zi9B7I=gU#0hUlTg#`Ur$VHUoNJfIsasDV)H;R45s3Q`sl_Gh#cdK2WC6DZCW3Aqe3@0=7 zcAWGpN42E#br1En<>xM^Z2LbDdpyB8?()X+ZzAH001!&obfdRHjZz28E6JAz1_0cq zI0YAa>;Ywv4hn3w_-jPnUIYT(Qz4*Mf)K)Pd+(g)^rE|JO@$d4nsXNbn;T8J1sL5^jwYB zbZ$@L9$&sxq~0(>rx081+S)MrBJ$2v!ac*cXAoKUB@o{eM_y3)Noc|p2gX2g5SZD; z4pMtO)x;Z7OJ-scXBPyb$5FB?5Gdc}*aVH`=#+=TIvdMBs60220oF3q$P|#0eYu^i z`H}JRSYhl<@-bF}9p~vo!pu&4hoOl{QZ3lZJc%@=M+?9p~jmm3e&b!l0%Uj>IrlvsXl z8eu~|)_Oi~?tjBVru(4d@$P;4;z@kifk+=hZ+RrEZ@%K8%Eas0kE7~=BO*etXZMJU z?mYMOzS?evc&ZF#Pu-Qos(jhIiF+5jgJOsWdn`wG^qs>ddU?0cU|f#O_ar2118T-U zQ8P{u`RZHH+++P~l{jIPQ29j(T(~Km^3pwsRVt?mg^3Y`V<{%x7PIZy2_q!Vp&!j(_Sa^~M+~NtP6axX9nc=F! zYv@*ZybSuD1hK~3*S_P^o={!m1!=Ur>tU%*6Z0c;*B`)ogihyxx?u0jyDw96eV#}1 zYA@TM&t?O^Xpc!C*GBMb<^9|5w$P?AkcS@qwxt6F0QX)O2autGzOg09uEdg1DTcEq zjx#0D3G!*F%yCPN94RywC$tsG{|aQBU^K{&owb_-O5uvL))rkwOFZ4~xP|T54Rs3;0M9L-+RjIVcTO*aaNXx61)wFxS8-r_YB>*?}RrC zbZ{lyX=6Qw@$BvaClM7mTC1KQ#subxl#5nptCR#aB6zmGozajjSeA^7nk`dxRB6U&%u|LpuS!MIo-KR@O{5wyl-$JR zroDGjA&bO(WM?KjBZjl9KdEO-z5ekY_8N7!-QwM+MO^MjvyswxF+U{B^MftQL(=`Y zaq}Y4^)Ks%S#GFTeJ1?{LsL*UF|i4!>%?e70i*5cN|Y4k;#|oipr@+RsY<8GI}+bi zXK@%W(V!1dsP(7uxX8Ma%*}N3nbokx4wE(a(g6bEkYB6jcVT&M(ct~KPfO_msW&>XW}+p54E2sj&UtMj>Y%Q-a zJt?~!yv~wI5vt!5)*HmEuw3??vZ^<;z1Z&k(Omd;$=MROn;V2}O_HsX z%D9~q#Rb~&YNoI>;XK&n6@*Me1@UV*$Ku|JF4h7?%8PAL!ehF8bPgX!D^sZO;!IS_ zOzj2{QA{wI zQPS&RkwN~Neodt*!~mpkGKuERS`Uvyg(VeuhA2DH&~;vVkt1dggfK@T29ZWbTYD^? zBpI(~*A-aMUvilY&G3wDd;la5)Js5DATSfmp=VtuY%Xq+YBZ+Q-`L+xI}ue8r&oD! zG_*$*>1&}%VLunWYK1YTrXpn8!(kZZ03@ML)BOWh9`y}81PMy)y2d?VWiBXTt3!CP zF&i9VFS>aZPa*Ps(Q*WTjDfjLti3%dOslAjK*?gKcQRm5G*F zrtnm(>DEeI9zu_(V%a`j|44nYN-^LMYHZL*dB(plsqn@=6f5GLp#;BoN< zfuNveRy#<8ei{83%Sy;5P@lW!i7p>P-2X-%NYvIRG2_a$|7;W_&!}2)t{l3>n3YZ- z%zaqw-vvWFj>Nv*6melWLcdHq_PEm&In*R>6OxHB-{V31)7q#LgFVaZ;fKZDonAn= z{H1)4i|2L;!6CI@3JnA17mFJ6Z*?o)dI<}JDFue}zIX7y2$+JrLEd?#ZX?*E;eDlh>RD{bv@FM<`&!%k=RUAG*H&ilsXie-v+kUTqv{Ct`&{9paj=Qqd=%3 zo1EK&`-{C13jX`X(Jl!O1@DnWaF6SyX|NEV#quPO>joLq@}9$97GMRzt^AeYZqZ{g z>!UdfEaU7d)Fv;Xmb8i9ZkvOoEsUhGdMSzO!l3onsbfJk6gz%r-?;8^{rSk^iWNY6FU`v`A9X86F>F;EL<-4+j zyH$6nQ6v0cXNnDm7DZQ7?GE6Otg%OZ5f@Dz2S|7NP<;zx49D&qMIBF}x0?c`K z3R4Pv32hA91SOc?2(4WRWsELd?h!ktQ!?>Ryd|W^Qh*K@X$^p}5#*x}tn%A9c5^0C z`5i%(<@v3s$5sP2*VWf>vj5@ndZpth@rt3rO=t+84! zzB(bK!Cw^DJ-=v`CR&LM-OVqBGxuiCb|SxGqfwy#s5~K@e6a?g<#5te_ddZocl!%F z*+WiS09=~%*{sC|DaMN5_La$u-gh@q8R4+KHaxaxC7NAA8m$=dUw{=e=#2!0^^dvc z`^W&V>rdzzP(R*uULZX39;e7QIfGiI&Fe z?_U}*Hb5FA;{s-Zz!Rs{-xxavGu{Q}DPTQ^xX!c>Th~X=)GKG_EQkO4YzO06XmNJN zHaAIwDQl$TclnA!V#XoG4rlVm-!_g9#X*(Ye`%%tZA-)km|{j&Cq1J~@iPYvsu9hA zYmi;V51$n1N5x40uJxOQF=fEXcF~PzXP8-H2NBY%{(@b@U_JhOo8oUf&VV>M8+s9}Vyw_(P zepC@pDy-uWcPAu1&t*AZH|7szgB6Hn>quVnW}h`ZE$a-rfIgBEFy8}XhyezHX3M1G zt;QV~V)mC7j5kS%-F+3l9_)-&Aw73*XnkC9&A70XdEUXdYGK5m53>w_>0ri4$TV2( z9RvhxkNX@SF2~p!(bGC7{|G%UK8DwVE%aYF<0xdAZ!8mu zzE|%blo;ecxx@{^%&@=A@1kTh@)XM`qV&=_zx+yw`eN*w&fo4+pW4a`03H(56caax z|J zwliPx{(-Kv?+q#9PL(F1(X#Gc94(_^9U{1b&vZnKbJe8PZHQwcy~q2KE=u~5)7E5# zCSa%}LDp-4~$9Ss$&MzvK)8Ob!ozfc3oEyM) z1qw(CV!Rlq8xZDuZS$gnNfoSgel%7K&bG%&vg1{QE46I%E&+ZN3=xt09eY1&1L=fB z8i~zugEX^Ph^-xlT~I1NEQjiLTfA?w#0nay?+w^@TYc3HF8`d6Skc%A}yGo8maQK?Fl>769(VXjsqkX_=?J}DpH zKu(MOn_w#3O?e!1<@)6Nw>MSW%TMd8g1E1oARdA@SANN{`)25Ds~*kE(8NIA2(O*x zemnz8WFEmRuL+Umq}|OZQ)EaFVu$M^!(wol?x9czVKET|Dt7+!E0#}in3~zM6)mME zq21u4wx`BvRunV4JZtp+RZE#pKUECEmSC9|%p*`AIvaE3--&X{Vb={DdHt>=(dL-& zkM{!6uvuiyXqB$*V5S_YA826A)|=B(ZOA61gWeeyPA?Ycb(xgJ3na^xo^_>WODIpaw(Vr4?1P;x=J;<#g%QU~uyatNOsHG_e$lFMcejKE%yt_l zaMbgmVtXsP3eY{JAZVn}tWI4+L|z^}G@z$&M1Lm$Gjpa~VP|PI?iYnqeFooOzL*GSFL# z@>9~5-u%BxTcQs1!0j4@zPVp(q3vKRS5BmK|| z1iL-F?7cUpQ%-fe%=RO3M@L7~O6%0!7Brw*kv3KIg%bl$0k$`u9h*M8MqyJELf8LE z*ue}<9GhhOC?lGyu{8f}Jit)106#A5uq51MI{EQy{YaB@IC&pfDWkxrz3{Vv&y?sI zn2Qy12~eAp$qb&w6$XQ#@OR__;9Ch)2|b!wtrugoOpay~tc-(}O>VF)UM963FG{b9J&}9l0eXv^-I6 zpdeE)&HH{h1h>!0X#82j%V!6^9_ZSK&|XGeym#nYZXmbhZ@i+~rO4JZKNGAW$^C1n zaw$aza$oRwlF?FfsAF~GeQF0b`Ir-Q7}WaNt*>bK-u|AAPE5kOU4|NbF271U&)cF}^fy-ebR*=(ndO;ij z8H3N|u*OS!8uRh;4+K_BC_{G%!*i;rxj;Ej#rOHwkbWa9q5Sa)0Fx&JU{OBuQ9c!9B2`-V@c)p~rnL|Zlb5#is6Tb6CnPZ<{x2Tz(SGq^@HEV(2B!(Q4WyiP=;^;ZG(-a?we2N&Zo*~@xUqgfn5X8OK| z!aB*ZN11`|b(JXbaOBwrX{>0SZk!5?k6?DoU}TaOpqyvhkc1(D9VSUBq#iABSfay?y+(dbq9y8k#x}Q#vMmO2RICq=wDM%6xV`Q0N6UqnM&Kg|I2bjQ4s!Tl zZEBG6bn_|psSr#~UA8o9oCi#J`Gbu2Fe7y4o=~ftT)!$F*rkjQvdHh6# z>hNf(CuQRsIH1IZp1+ylvKbz#AEt6~Uwg_E%HUNy=^S_M#41=QL?uNtDy#u0V?zymKM*;VN4*u9I_iG(;A z<7Hzv1pY&M&(L@!84h>ijmPZ{zum8hG@6IyYem7nT1^*aM4US!3#SPc?#m{9QiMQ#iqR2wtFLaG+9fAH02bq-h{eeQCl=TUG~4m zK5hs=@>fo+ai--%$O!es$WtBBJ*};+{1Yb{@~C`(36=fV)!7KjIg!CX zNK$Mv1HTaQbH{lY=Wz|N?yY;6nb9h!e45_0cC0d(*||w%5_hXR{3niNA=Kpvt~S5@ zL^B{j(x6GtTN2p%y5qjGCzFTEjQiddaIt~kE@m4~R8EVX?!J6P1nIfy>bdYp z`_n<#SxCeODp3~ssr+*u=;GLI0;}bIeuomN4Fe!Maw;3|x{^9uqlfw(GSDdSq2 zqX*9~!-eJ6RmyHB9%Rur8f9O*59|{FQVTO-;<3$R zSZ@jVGMOKb+s<{bEu+2{D^K-*k*lR-Ecj&^Uz`krFC7c-+~40PR%UJwx7(k5KG9R5 zbsy;>X9e7Zn7*Hi9ttN_)}VPDdhPD+H$T(8L`%%g8X7Wq^#j)LcWz7HHe@3xmKI@r zMkDMy4^6R|Db8jHi?elAw4F{1s%9Lfb%-&G@sF{&f#}XGER6q-%@pHia?P>{eNX16 z)*k+R!4QnWv15J!eKX{9)a_M=AsnMSZW9%jc|xhY5$IIF(2Rg6oqKGwEwLGfu~^hKo@gw zh568J>Dd(Rq|rsk!&ec(EYJrg>l0gEq^nYnb>8%wQyWF+)6nAw-}fmYSN%OlJe!+f zp5hOY-?xG>S5IWOo0)zz5nH&WzjU84i~s}r@pCpl?yM)PpC*RpRgh7w$Hd-$XmTH9 ze7vE??q6jQ5=f}^^ak{p02-uKU+XS1X)6Tdp&eHXYJp2B{aS@zd;NtXOaARX*YoaIdBXE5$ zkzKTSri-CT-0#Qu-iMwTo_2YQBsOcZz+2FOb(Wq~_sPKU=96VJGCwxE#5eqT!!VWh zI7Cts7EH>W`H+Wx8Caz(CU1D^$j%7NF-rbay5DoAu8#aF{Z5JC1I4c6?#M}kJyVy= z3vcI!hU&IgYp>Pm16?w`D;+|_lTC*)-lF@1JNzHSLP*Y4&-vRP7nn{y>Y9Feaoo_E z?6jjfb-C(eC*xQgu+v+cm9E{BXnn-BB>&XDc$Me1AzYaZIR<`y-w$XzRQ_%|{K3GO zwLL^;4r{-o#Gbz8{TkmIu@py=26fzT(S`C|j8(FJE;d<1-;u#ky2B18hZ8D(T}@`p z@FlT5*+?`1Svt2}YVL*2Hmi-{gBqTZP;^~V@lhXsMSASBOk2);eWuENU^{F2`!1?m zAHES{mB912@%YCTPGsVtLc~4|UM6S9d;alz^Xj~&^;=O7+V(lj<>roj%I~_zb;A!8 zHcRAyE5IZ~)d|&C_CiQHZ-!q^k95EeM1f|M*x7Lv6n56nDT##r+>V+swR(c;H68=I zG~2wZR$yJ_BUq$ulp=n&{P4Z&czmSZNlUb?#kyKkByE^8R<2;f>Db8eWVOVgD~z{h z@wwrz#BoX=fcJq^!9s;WN+k&2n!yx?uQRNX9S!P-DN^PyFxN|;(Xu@>Dbar%qjU#7 z&C#NgwaRbw16bZf#0L;GFFQ9TD#wtCML*{*wSAHGpEcqPC6^0p$PH$B|l@j8qtfUmHzx953}V4cuf1cYMKIH}KM{u$64MM^=gJ8`*~+{0 zrz$vUk}p0wfhEs%N#v;CN=o%Gdnfcp!Cdd@DbgwCBDKuIa=C5+&H zAo2K9hmqg$rpkwsOL6CUj-4FF(`(Tl?lNq_?@umg3t=)=9flnfB4vWdTXWaQ;ng8u z;?4oAwCT|PW(89V|836q^K*Za&h>mMMqCI-5YxQqZXkR zd!MoJy^(CquB3au0D2`atGUS!nJ_FzP_{lr7%;)G$5LqQT&dNW5x92U;le!snFH6o9VEfd0oT*Y_7UcYp>LdT%_p@osI&96wz|`uM|KDT8O~!lOLZs3T!7 zF%E@ezbScxl6m^PinRg&T^ZmlxU^Wec@b@|wjW5sf{>Jq{ zFvH2ie`57XM*NFs(F^#Bc}c;coI}v$hIFOrPHh)x2xyvI(3V5PJ{T&(1bq^nw+9#b-%S@y=sPFB|sj zbHq^;H}PBoLRq|Y0=zB5CbgpBxgt^ts~auYr;tBbwzLRP)T=|Fo@Lkk{80rHOa8XzeLTWY#DSJgu6bxIa@o~iC>K#B%+j9IG2963 zEBSl%sEOgrO#$Ze^ia->iU-$}l$tQWeA*l>_~#~{>L-;Kr`yblAGrA>4Sb8wiO9}< zFmj?++loqzFyQBQ{lcg9vC=OtYOl06-D)_GAJc>eIuOD6fn(G2V<}^GkH%k-VwQqU zn<5Td0yboTKLwW0xxKuHL!L|)GVB$X<_|uBt3zzZOS+E@YY?cU>>9`2!K(81d&vE! zD{4?0>zt{9s{tRzY5xytZ{Zhp*R_utG%7=5P)bS(27+`qg3>XFfFe>Nk^?fJfOL)$ z5)PmO(k+a1Nl15hcg!$w_JDfd&-*^-ch32oe_&>RcdWS9wXVhNeP#uGa@BEzyiU%y zFjN64T+7Sm!VrXFYbHmf>WrmR zb0)N`w{wh&9(xIws$K~ZV{>WwYM_IQ7?Y?nc(3+mZ+z<{bi(zmX&V&(>>FSpG`qHt zYUIyBLC!^&iTh4q;ejP68}{etWfdDPAKC<;7-G0amT4a&_L$6I%iIM08TG7SJKkX= z@2R-YISN$V;lmqwqnie!zJt5C7+EXBO5d|+&6^Uw7zuIbGv57MjEvcL`8;=A_RS3c zQby(DoTvSBJlyDc-U3mm?Pn`%t}_jCC}^msw%+TFIYF7!0;5l?$@x~9N>=-2J6+v1!1LNQC^9Nyr8tG&dTWHAoYS|h%c#3j--&YE})0^F0Y zy>^vAI@pnK_m;gwzc+iuHy(T)hDYxzx(r?9ZWP!Wz(pLf?|_iwR?%bl#gnz@9kJc zG0$^=G`xy(s(RR8z!~LM^29&3xrZ@d)hf<{_b8DEqbUH}_?G!q}{e{_vx_3yM+uV-ecLvkx2M4)bzAW|t-+X)o%t2IC_qA7! z(x#20G5d{&5<}&9ogK=YM95XWh0xkaMVz79AYSpgs6IYaUp^E8F41K*S7`%dL+AIL zn2sB;m5Sw@3;X@Ed6`SBNE;DnDYxzAuC?~tAm&-brL3j<%U)}{HO(nJza>NTt{r*s z{&6D<-1vOhgZ_<+dZ&zwn$l_!HkPm7Z`PVTJYrg4I_KEWZSp4B#uiaNB7$lu^(l^k zX%YXuJi2jIHP0lh%!feflV4nMe=xaSvwh%Wl(BMUt|)oQ*GScqP>r0QZbNPNMK7fw zLbNpZS2R2gRZr!isFHP1@4~#dM?KH*Sz5tpe@Aci8H|=qzHqOn+>NJy2!?NUS(<1< zbE4+&+fLoKo!tqk{cTrO;!{kzltj{>>oaX+xKX864(#sSJ1o(oF^Rf{hlH|Uz;uj% znkh0sK&&iv0sRB_bh+Q&(u8cZjS|Q-c;%-bf~0jLF(iME5Z+L&+Ckxnsz&mItMiFU zhK-F)djiiDfC1uJr3+tCj(kqH!L7%I5Ic8yU^X`#YJFAKX=}Iot2d?A${43-qt5Xj z*~{PTTT2pbirZYw3VB}PjX`(cQ6sW>DYdqfF9rGAUlVkIDg6_8f`9^x{Z#PStRFLV zQ=koc*pd)y-kCeeOR6(|x}k#1$i2(`gR+=sVTo<_($Fs7)78hlAEP-g=Fl%2xnP>` z9eGApho#9Ku>y0pnjeG##}g18O!z^Qn@0LXK2^Rpg+3sW=ugUaJkaL!3k(T?&ex2o z+nX*Mujq%*2p#;W;LSJ5G&}ba}4Enws}TU1YYdgj2DMsbIST4 z=?UXuh}ADOli%%5x2|%rVrRvxhIW!l{#D4hy|KFZ2k?0diol^T4>!m&joen+m!~v; z@gd~SooV46QqM~Q>&Tgr)=lOgYTkVY06OsOjX2! zXO;gpaEgM}5sR}W2vYSJ5RX8C)P?ADi;|ts6?Cr2v(Z_?2g*f;d#(+`z7==(X6&;r zfRujQ=iytz=<@5uvuon~MXWClpoF`Jlg;oC*s4_@G_T49GEpjzdRO#XqDL()e8qe} zHufL#%Rl{YAYrK7(p`p`wGdnAoyKe~>Q3W@dE0Xl=A55CC|wmdH`D0nvPC`B5E=vR zqdJAWCj=bbbLG)+iJD6cCLQyXe&Ca)ojLLEeIn6ZD_#8NX5suo6kNFYapK)0hgcHT z=#r&%EnmV>k(Jw(TNMU85Jn$J%U}78`Tn!s=y*F1eXkM{i3_C&^8K=?|GLxjNErpqUC*PL=Rd=#WU{4hh%|b%$3OS{Rc`onqt#p-QzcsokP<7= zKs-m{FT$ZCHpb3lt>uEFoTNYyPf(Q))~dWJx%L(nUhEp$-?fyXjr^Ec#2) z`d9PeaS6H4VKfs*N%<|<@s~@d-H2n`bcL@$ zXuYWIwfk9~b2@+5)81=Fxzr{LYnR+rE8T05wN5lLBH$v#3b^RPFmFf)GAVH}?3zp| z9hw!N`H%^N^q`uP9%8L~5mHs$?W57q8MqF$Dhmmu=5;G9jM#d(JS8qNewYs6pS0n| z-S=)Kp?192kmplO(07@OTU!)0q#$9aG*F8CO~Q&v{hP3Zu%~9BXzd2=>nJCeDTHI2 z*msL4{61gLeZC#*sGzeG8bznwIiF^-{ggI-q>qo=z;XYV{C;z}$QXr64$D-=OYnqD z0YwQmsS8bCB~H!1J&atYFxn!jTJG_R;hY>kan;@RPjoI(@aMrlj$Iu;IkPE>? zEd%vSvgHL=G3|TH%CNyf9?SO##PLkL7o_FOF9Bef8bInP1cl z3s1+qm@murx(FTVclze(0CtEF771f3ms#;_Q1%T-S~xy3 z-|PI&@7;uS?jp!LfD;l1?)RaTU4ymKyEqYCr!Ma?n>F1`CeqMtl-;UDUL2-m!|%M_ z@`U%P)vV~KS#-eJWSb=`TJEQ_w&$1;KBKLKe1|`h1y)7pmPvOg>wnE&`TkjK=TTH9 zNHuY{J!XqUWRB&ap|dT{dbcJ|_anM4n3-HE z0iaWE1(Qsy^LdQlvw8%a!!|0Q8k*yWwIC1B^3t^X@nSW}b1&mq>u5_%`EVR(9Iu(B z0SUeHWMFebpJ}E=9Dx^38c%hw8Y)#l?4_G6S z^8+GgxPH~Y9G%-uz4CWPnGbxiS?gp6^PiyfKQoLUk^JCDRUavEe6a>9CAZaqRsrbN zcNE)4&BR!Jy!^3Ce5_^+G1MG}!+Tp2l`45jZ~{;QKAPFDfm1>pQ$Vf4-FEeJ_a8of zN^?}4AU58Tx~1$r^kfb3AVL4-h6Iik`~}l^6s2RlAHFtqsNodu>Fw5kd{6`$B*M(j zWwBfgq@JTa)#agYR$j6lf)3+>e+WQ)$mQd4<{%z$HQn-)WhXl>1xO0*lc{fw(rs8dbsX96ZorR! zITV@5jORO)syVI2?#>KY%Yv*^z)7C|fPn8B%i+qs8Iq}QeQj#R7t+*W2u^hF>!`O+ z7uf|rmdu@;r+~uoi&?c}KO9rp-N0#zS>EK>gj2#V569WL>AhhxZ9Fa2FgBj*^BqTr zjzx~8_;dlz^Sjv{@SY2|$-G60T`}iM-Hl_Bkql(0pYrPvJk~O~(YGN0#84@SNL*4Zupr^=kC@BtG3QnDB zuG*SkwT!I`Cq z+IQCfFkc=h(2<}SdR24bs57P+9PsN0?3{hi@Ay`&Isu$+w^X%UO&;h(Tw(G#$6%w> z5F0#`RQwyp0H#e$c!i}DM3TsVZ*L2U{2u~9o+62{ zp(`>A;O;9{O-wk6>^(y4&)Q~M#meLl15W8Zjn#Z zj9ZwvF^nwQhwE}j?@3og!;@i{>P40V-vhBsO6;e@ zrf3&@e%OEw_`B7QMP)9gxMM@bl-zm$iVK#uJ2-)FgQn}lnVHlk&Fuc?HYmX1saImd z11O=CLVYo3(#zji{I!kBa65Bp^fN^&sRbYRp5fj|Nj9J+oYx~hCv73NFZp1Oy0Yt$ z=fFVygWd$2kGi;>BdZUw#tF;%vJH3fx8qE@s#Z!OFgx*(@1g+ox4w=OI%B4vO!eug z{p}|keA8F4GV@^-9v(Z-q@D#G|5cdEd9t7h#_i7fqfE{%VRLi_OrQPyE+bZH6AApX z&5Gzm+W`9^&{3XB4e|mIhzKZTJVeT6Z!Q)IHjB6z+`J29s|ciHMcpcvfCy4j!7`A( zz~}3?SnRRttFW1F3|K(;f88!p_{xFXbTw8QxSu=wi`qX%>woUIj&d?YlYJ_0r6M)Z z%wn~r$Qt`e%nY4et(t>~?dF1i@jfi>-U<08{7d8uIAR3wm6)8!tic7UbmZGeaHSahEPrlpF0Dn|u!pK7cVb)4$`GlksAO;_L1d=#BDwy) zp35S3U%1GOa(^?Mf1eI||2(cdb+WG3DKY8U!ox?NKS<#?O;XZ|D=LiGg&yMSw-E%h zEdHUTYoF59Ur5<0-sq=u4T2U-vRGWpAe>w)R0G%ly-ce}9 zfuAlLg){+}iScP>zlJBAI^2KFE`5u%{olJX{?$!f13a*38D^x~$)yyJsFoJYKeR`U zZUTi=H33#AO{%)H!=l;vO0_W>b>xAGnjr=cI}RrcE+}ef<~(O6sCwfOItNIASQj7k zTxX91@h)l8B!y18p`b#kJDui(T~%b#L6Hh#a)CNXLm(PKhJXV9?$`Xrdu^6_Wja?* z%%S8T-}Y}a9!91!j9Krv2E!h_O$T;%L(d8Npso!^dAJEe7Fed|7~>lJ06_r-I>y2q ze1igyMrX03oe9{_E&|{cu>+C#@33S>0pP$=fB-21BbUbjZk`f9c zwD6n5T|Yhp_+uh>z^-=_^e-O0m}K$lv&yI9E_>QJslZwMUO-vWkl{Oc_!hN3Oji?1 z40EPVF`KQ~J&+oCd5f&}@53Ziu8KN8pU$d5^o8tWirz-37>b^J)asf%>RC1*JX1Wr?I z`~{Xzw^iSAW-`hAvsRsaQ|i2JjF^NB+El$LX#Ll&)z*A{N}o9hc4*=B^?%Hj%Qa7f z-#SCrFNTp(?q+a{cKpj`sSF%5#Ky((aGI~uJkf}!*e51`IZ1a#;2jl?%`?F4wUV~C4OCt?? z9i9=pq8te%NRz!;sSRHOa4~8Jqb*n9owW}?pR8%y3Hy;F_3lw%{uS@QnjEQC|KiBP`~zu& zT-A0=E}CQl9UwN(U)xq{d-(pWXtc-RDJ zYd8{q__a(;r*2=fW%OIobQpXtVZ>s)H;a#pEz???F`pxN;c*eDV}TeWbnuqlKX0;O zH0lq|E;m(OBT5?u48<%%4AUP&0kp)}+yIu2ZT2kKQx5m&`I^V_5{7k+bFaE%bjPNw zTP@CPbCvb;Vy#z>*ZrEqgD96vsE;Ewjz49$bP&HV{#FLAJPa{^zqh+4oVf?>^evcy&g?=W+oTyxI2? z-bID*hZ<*8I5bJnyIaatSy@H0^fyyXJdb@Duaupssi}Do$lQYeW&0XNBmdcFZ`Sdq zw_Do|WSOl0xy?Lan|+v1bq?{hqfqod5m2@ZMuJMAUMz~#tUr9N0@cNz0@^?!B&C$M zeK0v#=o{*g65%Ks#QTYnMvC)kJ%Hq=OJzoy|MkcJVRU^9b`5p^)03W@FKCnSB)0EJ zss4dtOk#aM(e8NinXb6=CE8^DxIK0u2r9O?bBk8C3z8TZ& zD=+zaIX8^K>;pogFTx2iXb(HgP>8p|3MQ!}o*TrNE}g$bsAzv9Cs!G{iFNKEvrd{K zBn6Xs8j}DSOG6RP5#uGP!-qdD>cjmazap(c~=eiITpq1<-^a|)qM6% zDeHqaa_Qmct>5Wx)+-vdv$CJz35&uJupYb|c)vNOBh6(4_|V z?*vjWu?gE10O7`c0`1`)g|)HC%ick#gDi>J^@PK##fxES-kV~APkOG+@2$6aF3WYb zW*uP!Hy;P>Rz3Ta5ofoJUEvr=qEqpWrPxUQJXl;zR#2G?9`dXauQM ze)h&XUs_N#?S0o+)=eK4#grn0WfuP%C>ZG%Nkh7)lMy`}ch)@uR9*PPEEWiRTGoXObeM5r6g3ES5% zW_5I8P9G|X2SqA&LKn+7B*h&?B{=W$;q{*P17YOJib#nhJ@E&fJhoPOzMMUX@(%UY zzQ=NrJ}^Bn=e7N=j^$N4hwtjzvF4|-5fzVXuW4VcOhOGWU~cmp0+R%od0yg6DBK2s+ZAlTLYf>+h^H2Src zcWK5}^(EWT)Me!Q3fpir{4Hdt(fX^y6!v(pNgFs6<9=2u-Du!!;I_J_D965{`TU|4 zy`Mok_m?|1N*qRil5F>E7Q_C~3Vn(P)-je`E+0Q7; z;sk9p)n+)kMNmA%B^W!ntnT@#H%ywBIX_3pJq$aTL(*FrYGye6n7(Ntq^UX-dB5~` za!kH|!(+EzDP+rW_`m)jGeF~pz(ZLcUzN7$O!U!gKZ{_v7OJ~(2`}1HUCNLkcDpfO zx6-fK(wvcKKypxz<-?Zzs5H5Ca$C7B>z9aE8TMIXupvu^EzKI|r1OCRHfOCT$^%MK zNr7AoHOqv9c303azknkbNh3VW`rwwhl{wUC{y$Q-nPEmQ(T-k6vOC1TL+Rs7zyPwy z0V%xya<&01XYJW8v&f&ep_i$`Sc^yBMgv*VX z#NB|oU83!m_s|Z=Q3I?V==r1^9|mU{D(Kwgrt@)Ygf12XRX&upN6%N@H0*AYojP$a z-QgTQUBv(6#=JWYLxkRpxj(yx&-^}LMT$u$*I3P}mO}lh4*N54eF@0}U9R#2YSU83Gf76!k|OP_8-KAE!X-R9FxuoDE+dz|@r8_eoFdb?+8s_KBhQiNcYY_YtVcwR!8-WQc358%l z2Id>gSy`vx1^K>-VsS1rtbm1t*-`2r=Y%7_#;T<-Y2yns7w3TEA2VjyI!3*`JiMcz zJtW+C6zmHx9!Ro(dEPOdjqYf>JARgFouvZO$u$bGax~!kH7`Sgev$rpy+iYcBCr13 zUVYkN-K>gjCz3NwJWUaS|2Tt1QL~s47ZnP}_)c_yll8*sz{Bh=|7&5`pWaq~vdn*; z1{nBIEaD7+GgT7FoAmL41}_r1C7NU!CH;~=QyU9cKyusHn-|TDQa(d_x#qG>Rcsdt zg)Qq8K20j?#H-aQXU#}6{p!eP2dnZOWd+@{$Zk*cO-RwG2M)@`rMt?wxdT91KKteK zos{EaeAF^L3sTE}rE&jSPuNMulg%ZVmu1IbHw9vYCITQIq^!!SVS1lEXsrX`_^dG{ z1#)IS!Y6pdcSM_j85v;_cuTm{CTtS_U|E;-ow93ZMsC-7htfUZCCQ8 zLWDX;CQ$9tI5q1l_r|E(u8jJ2(`82#ejL51m&bI7Tc z^Pef5vLuu$_g`v|w0aC5&)5KSd$ckQ|71A-GwwM4?#yG>wKSeE^WLd9CcCDMUb&R) zsjtDer?7tVxcinb_+@;?Q%>EJy~pGE=^myt<*X+`G>QGSN^9D97c2ox{-FM@W4|ka zq>5ADMUM3iA#lS$*5=+C8R6_rb(B+r4u~rSVVg>SP_}jBNkHsCyN)3+kYHL7%!EL!L6V%7l1%IVv5%D zT9)ZHZf3uB^7nQplsB^jZIUCjNzfBN!#!k!bSNrbZxtTuPr^6FN-%sR z4Op_qul?2kPnLE9mk$i#Di%5HCLKV-#>Bry8wHeCMuRrC?nnYQ|qee1OEUfqIv$%L9+z80E z3p;sn9$kH!@$p{u|M3z;M*za|g|~OyUMP zQDyuHY;bKS<>+(zP z`7iiJF(wJoLtR)ES8)#f%@qDSMMWn=K8~ioYV%%Y6x&ES>rH9{WiS+T)X#PWA0~r# z?L6l8AA_eLvpE+5giKmH zBaocI^5JqayO;jd#V#Slw-0W*GV-k-o_> z6j`hOreq$yru9@FLq+fL(ep*Ztvi5#Vt3{x-Sy8Q^GlziW2OntyA!Sqt%krai@&Nu zaWL0gi7$Xy%L92R0a0QS10xIculDS3PW|@6&4c1612wL=8Q;aK=#*~= z&6E~lYja~?i9YXFEmQG1!hR$oX(3J+=DE8ZaILbWh@K|n0KE=YuTG|&C7zbvP{HG` zNy~(;Dq^C9_#j}1hIyizs<;Io&lHaU3l=QYZh9llPsYpG!?l_Hj0{00ePzK_>y2hR z!KfFX`&@Zu^BYb)(g62XTwOy;9=N)vTTS8(V(Eb)8LdD!?3#D?h>^j%sDSV;C2*BF zqtv6rty-Bz!4-$AhkNg1M=CJ6mz{*%_EpQ=E%$@U#CSTS91cpI@Y9BJo$O{Z3Grt= zmp_k9+*2pfZgH=na(4;E4(sc#Ohut(H^`&4pcYR6n~8U29#qL{80k)CrM z;sQ}CwrRZbjnfrMLt&Q}H(Yx^fblj`19>b;Mh#r}m9Mh;dY(r-B-_vMUFE{1d{d+; zW2T(%r;`{U*3Jwkh*{8P`4@qR1qy*F+E<|}i!nE(5L9>~*Lz$m??U;#szg3WQ zXRpdJdFTJH)$h$UdyzMYHHc#q$&Wlj6ru?;ACiNDqW~C%1kIiXpXcgv%(rNIm5TaO09 zDrKSKclK)H8PD;?3#T|*3g9JomEgK3Ocg7SJ0w1k8NGO^dM|Z+M*$$Y`nhUOMgn%c$4PQeg z77KW)_9TaIm?7F=?z18?RcDHKz+aoH(e&tsBz^n&N%I(Yi~eB`XrGG9o641sRx z5-gx8xk8IZf`!4gsYCnX5plh)3sDkX0pFu~Bj`OSp(cg(#I~}yr&@XiP1I9|5bseT zD4YLPv<@vW0u1+l-!_xW8SMcS-V(}!r*}6y%@3AoN=4ccG*$qOSqz6Zs2ItO4u)#B z0}>KA4xHUOL9~-1^;~O*aN$|Yl4t2x6-2HgNpKI10m;Xw(Y1>n{e@J9hBUb?wALDl zL4^$lL%~oQSoRc>0E6uVFM63+b~_742nME;-dEF(viQ5U_U;?$JR;BTglIp@)!MYd zfOL@N>1(Qsf3D$^=6ov6*%#F?%l)tVp%Dzd_K{X>T?Nbt%6qvj2%Z0W(})Pjb%?!e z)Cg$O*R%tT2;V;&QVf<)$fi2yfguHY&-Jy6vqkTl9W4M&8L$JL_TV<274lQ|&W!Tj z$cH9E`C_R8x&G__fqJDSNY-NWaB~*9EG~b$-uVV7Xy74c(B{m2FE1)zNv*Xd)t&Ch zJ@~%M_bhAfup9I{fh(Und7q^2@o<8A;e0PBh?1q4=v+<6`%nBfrLm!JC=IqwEC0Cr z?WUntD(P>g|1{r`MGnZdum5*L z*7utL8*%*|>Tdp+w@iSmW{w=GDAqL$Xv12uCT>HhA-!p(H$Q8x@ze*>&v|eg{ZmNa z5d4;Y@nSso8!l4_Y%u}@&G5ma;x9JqgEG_gMr)}}B6d>@I$o)E9G3k;0gk(F6&|j* z2s9uVFQ{`Ib}QmZDGXm^xD?;-wrM?l>wd|7lGF%zsAsWy0+crVhT^$b1|+6$k`Ik2 z3&<8vU$>to^zw>=H*04)FY3f3(y6YivHYjf?^6=)4BzP{$n|!W&_4TOB(kQ=~YH=LH@S@k7_fZxh|hAjw}i z(^W5eu(fdSAkYmvPGM@KjSyP@AxiVSGx1}jbi$T-c?FfsC^LJGxXbxu2)4%>ZBj<_ zZm*vr!Mn;txiTj)(6s$uW!2fzn6O{IuZpIjw=ltC2Ld|roHqbpj=BK6>>29KBM-_} zU5D>_cZkz@(&Os*Lhj@~?`2s=UB;%9M#5Q}zzw=7dk)7fg{Rrvtri*2-m8o;uN3t? zQcPdjYKX3kpk#kP4F=vmo<#7TuW+2XC+J^U*M7d!&1O?Y@b<&2k?`*7aJaTm_<5zu z4S&gh-{_@hJEbpo$N;$Ayx<#R*ZtuP;EA8lVA~oLJ{lkcNdC?wqQ0EO@uH_2yJq(9 z6*V5KF5qRmHVFSxsCH_FwSCuhHeEV~RwF$9+ zsK`qJHKx?v;p=|g@$Tdm8+i(e4})#-OK=q|>>GL%g1j7dhE zWUX^*dN1lQ*hZ^POvKV2mTCSVDc=;wj_<$N>mT4_Fijpj>+vDFX0wS%JJ!`r5O`N0 zv=P@>*X|}WhMil8_(>V~zf~DRU!37DJ`CM?SNV15@$YT&l|;bH;x|*q%4dhQ^XVen zEOE}(ow*pcQePS3dAKN%yN)=b7TMdA%j0Ht{BctLiDbnXuD4sMtkX(Ae!e51Qyyul zEV)%63^xD9y|ShK8QJ9&bHL)~e%8j<=}(0xyNi2XJ3@e9P-eHW)@M!_%T61A!wEfF zpr*pG-}ey+2Pn8yrquA{Ks4W^Q9J0Eo(hu6_>ux#{S$ncrllybwRg&0>N48>FA}I9dfMO z5O;UTttR0EJI#r31A^pOxB<|tXBfoQ4r?bXqeN2M=I|BGF<@`%PMYfErhW42NA!gkz-EjSM>b;?D7r+cBXmDFebQP zPpAB)9yh)LmZyO33LYoXIQ}{{gH6D!ZJw4LXjq6b&pT7HH{v}~q4498Cm`s*P0U*$ z@thRpr(4#WmYAFyri~1u^h@-^#VwU$=B_9ny0agFJ$8Cp97gG&9@sjzBp2kMN zBJCIgUm-{avy&%3hbf-_6p5>toCm=d*msEcM#%Q@zJEF{PF)OFK_SP!4l>wh@|**G zqYOMT6}y+)rj^U zB;y`qtpSYH`mDPdJajnCiB5S=9Apm~Mrt)7FF6SA312J%2ma}?HT(P=g6g0(aF6*OP*6oD4Uv%-9Z7}UvPOk3G(nH>v7!RnRh8j3moB(E} z*mP@M`~F=^oQZkQPA!`|K83Q5PXt}d^T&_G1xWN5;Fw44u7a>gkOBDQCsF06FwIGv z(vgD@(SJ7j3Bo1nm_7VeegJSJH7x^MMNM1Mwm-R>-UpQL)v{yN zyS_9Z_H#Pp$nnO4`VZ{XG{=4mDh5+pWbn~*Uh_fO#3vruwY&hWmf(%VIlLNbfgQX}Zf)05? zqD>GO*4?0vyLB*Cce5peq~#OsG9~Dwr@hA?n&4S6bt(@A{to9z8=dw9ZP0&iD;*GW zy8t$;kNMD>GdVdyBxBWxJ!=w$-q6y^WOKZwTR>os|0s1gB;gkU9vGW*C!Or`S>_^O z#HI`LFSo0TMz4El&u=) zt^{wVjeB}_fT^{wFTbt$&De%1#Zb;A_zbQJ{ebnj(QyIG~RR=7{dbt=aw>!Y+8l)_J*GhOH0 z)p$dj^xa>ioS%2u5f?~Z&mCBsQQ9bdHry!{+lvP|IeUgne(No{*;Yre6DOkJ+3JeI zULQrbc`_s3%}*ZnP{H&ECz3uZIEL=_z2FBU*HF(< zpmGGRrV>BLsuOUbKo~ctkW^nvkttzI>DEDpY%=QEd3Y-dNh@(?LCZbV(c_}Y_GttI z#`@W#&)&U`LWz8y!2`CJTzT*d+P7H0R)9YC$6xP(LgM8N{l&qig0P(PzPb)iGcU#u z_qDkJU$)-`J83h)L>5!dv9qf^O}Kw$ugYYm>88prL`-wAZGq!1rpPFtQA%Oo#ksaM zb9F7gT3Wsom`%Q3d^SJx z?B+1~NB2L7&j6tRqi4cFE;bc@}PLN~6dSxmkBjV&CZ!ufDu(rMk9XQ6CMlK~~j4GHC%)q}ZF zTI*hzLU=ej*DReU$k-8)nm|(?33rXN{7$s{IKZ`qb1Ta9RoDJj{O-2#;Ks! z5N{HX{JNA*UE;a$p5#$YyR4A5E&4?y?|FXH`(m@WdW@u8{QxgA%=i)(X<~Tkc@*Gj zGUhLs&7YNdkGGv60H^WO3WcLJ7e8ygMpI1WPl`YN?Lyx*HS{fI-1h82^w;kkP8Fdy z#OpYZHM;xKYT_lb#Gl6Y5ZC^kX3RH-D&hL5x?6|7*c#;nb-fZ7v;$}mzh;nMQQcWB zZTsqhyyXK6AhL^{Vy3=C{`QBy?0bTeIKcp9I81+VA{#F)1HPrxGVa)L>)>1x=k!|4 z3Kx=XAi|n1?Xz-<294AMZLSGa=&PQ-eZ;{Ty=~t+*<@SN=r>2`#~jm+mp@--b#9hG zr6j^Mwdk+bm@GQ9AM(2$$2q!#Z!$D*Sh<9h{jtDVb5Td{WRLH z3pV`uUNFqQnz3M}Wk5ikp5FZ<(-FKCrI-#NQ7D8@+)q%P8r zkg8GyL4@j0v*WqMW4nX`Twr1;|*chXiD7NQ)!+&`(Sn2d_(V_6fbEGn{R}1;GM< z&cU2M)vV93ceQ!+V~VN~jktli&vl?nPr{>E%B>6TqoaDQB#tR}%`*)h9@b5ERDK)U z^P#S9NXcmr24+^_WCoATh`i370nN3o-S<^|{_{~sfQ!Y5O5VKuol?rRxv0%mXAzjp z+}fg*VXMX&n*k2TCT@Il))+^ZOxAC?ny&x>x?0R^8kxxVIM_hQKc|ZS*}iXrxjUBd zU5%pTsj$zZlo8Eh=56*iE3x7o=TgvTG*hHii20z@B z*m{K0n46TESgE}0hdYib+lNr#j>|`5xE6n|eLW9z8@PEjc`C+@j~O>^V~5k8z5Qro z{=on{m2$%6pN8wq4-RDcVLNNzAqOk+>E#1(Ak-ti@|57R*p?hQ3F;8tFmtb%^V1e* z9@V+B-l~B+L_pEhQ9|Y;4ICb*I6#PKSjTW3fLgC-$xT1XV$e^TefJ%Ock~rHvzHmm zXILUwf^fUfqL{~Ry^srr_*{GHqHV$Xd9~y{dkZbg zGgnuq8fZdPd5m&D#qwSclMIJLEI+gRHB@r!y0V(ZfEG3{SIu_%b)1GYISw!I4h$|ZYPi0i|KnZRZamwU)xY%tX5)hSdqZ^S4Rm?oz3Dc?ZAeVu>@ zm#7>+V2FBccO~{r=8H=(l*l53vo|+B7Q-Va>eweQ{)SF*Q|ufG&WY}0x;q0iT=$5q zj58SX)NxVX1vg`tBW?I)c!jJ?t0@^>Rg}O^# zI6kv4(771c-LLHG;GwNxc(I$rccH>%DBYV--CdL!86c9qq=iFB{7ZPkCXa-RcNw8H zKbL4dLb`F`-&~TNabLYEd6cqNib-U9lT^4&p5NjFjRrA*QigijOGRpCgLX-$Ihk|% zzoQ4e6s8}~#EE?pwB*)UlUd6N^hg$VI=_9#JA@H26KB5g#${u2haTIv#t)oA#2MK@ zX5nTw-}lxjB+$C=i^$L0SPvW1og5D_^Sjrtl62lue1!kmUJxL538BT*Jh_%;tYAcLW5su<_(ELaXQk z203`CPw2>5ja4-?W3j_(i&Ik-=nYWqR8H9Ja3jN3KPj0{qydkb>VvsI8&BB*q50FP za6PM7)?eWgE+*DoB>ldQLwYHR4IkX`0ymJ75qF#$n z>p7>cF|(f^M|O>oU>H_^1N6R#Y{WZ2u_Gxz+1q_WozadR(3waVHOgN;T3$V`%Jm_j z&c;u4k;wk3=oi{^;Z#FFYmJ8^Ag9WzPmZ$>R7Egm)PD?+6b^9vY2%*yZ{P# zqK)PaRi?Fk-4@{;xUs+gZuRw>$9{WiRYyH{Yr|HoE#_zfAhx28b6?q&_r>FBl`CJ6 zO3KJocJF#5r!{!+xPZnXhW*x(ERWUS)1(aJ1llaGmP}}$QM!2g1xdqoDL+0~V+H{T z9+Q!u@CRzK`x(}<%=MZ+R6Yk07~*8!!bc+ZS3v(fxFP5DPIfg+RuK`k&~4#@q|h!( z`dAEH?qZ0;b$zCLeQ_dJR`|7CO8J2mKa`fkBMuV@EFNxiO4#F6Q_gIAr2Ddt_% z{oZeX-x`)`U`z97Ds<&$)m{OB2SDcs|NYL8;u>h*XxiB~iKLBpjAjP}fRSqwGLLR2 zdb}rCkTJSr_-g8|-N9iYPDF6(4sbd4((g>&Wg?Sdk#BC)tUi5!K=>9v)q8hm?b1NI zIsQCtipdTb4~S=pyY_#o2-~|~u#a~;L6%r}d$smOZMEmzR|Ib?(&RR1RZ9Lr;WR9> zW7SA1rLf)ru*+>XT3kaiD7sEW!qg}wX$l5HLX!dbz+;KqsXssZMANQ#e_1?lrVM=M zH~Vho4~0}2!4Mf4DnrLrcGq`Hz2USzp%Y=NahQc&UR-N7EdV4qF>y2n=%CPKu=Apd z{{n^c%0Ddvz+SW|W^tnL$x>3h(Y9tPzp$G`6mE@UpcQTeSitD-Og>a0K-X3W<%C05 zNSBeSbfn&+q^9IPYt`_Vs!_pXE$K zRU>4oe+?XQ!f)T6wJV#c+|4RMW|2;o*UE;!(r7RC-Nx4_P_X>6$ zz-_USfmT@$Uo`n_DQth!fFZPyjH9ac&h!6d5&pVe(F`1tMnO3*jc>NQ1{exu1ApRj zJ8z&M_(uQN!qtUJq!Xw#pR7k~hh{LJ9ZJml^$J=H=gHg&)RbIOXbc#>TjHuION^HO ze~+5q%eW@&Rd)mZbD$3Z_r(LVx{7bj9M;|NR&6BI4g>(Tlr&lrp$ayOkHs)acx1W^(O) z?|bDx$yK5Z^*uxIx)|tu2?zI3t*Z6=M2sdfno!O=k^y+bTi@UYu}~bQ$Jee*(0=yUMCfRguk6||=ukiw&eQ|RMSGTJw?AdQ zOwu>zY@+c`gB<|u^@)~E#Gl~B{Opul%WV$fcMFUa`)mFuE>ERCO&c)_&Girny9MSq ztMhJl2mB}d|JUDT9>lu>f-=7tn_`zmf8!^`7DOkAPuT>xG7OH(tUj{*M*H&U>B+#t zl3#pboGQP~9O1s%v``7ptrUnI3)KF8ZLm1_$L5B=%Icx53nTFpJORZD~2ALSJ6;G zCU*@6{+szon7#hyNlg6Hca^m^$w_neZ@2t9muAF`1&x z$)w|(GU^o=gtOP6$2cUP_)AO1*P;HELgQgFpZ%SE+it6hG|594e-f^NT79gtOuPiN#A=7=? zpC9$i@)@N(b3e@ad1YR+k@}&GRDEH!6P@albPX z9k-ai^_@;8xhG(G!!&BXoMuS`Jk+pn5(>X0WUZ*Zg6l~rTHn*~`El++`N(d=e*ab2 z;Q}Or?5A3PVW-Pl@xyfb2Y0~(YO)z920xBw9mGw_CL=OzChA!LO~GgCXHu=T`<>A>D}GL0VN2+$4CWn20Ef&wK%}*8g6#8C-e3yeDh-RF z+_gryqpp1{-;D$=1*2oc^$slCI}g_t#U^>zX`x7j*N~;l;Y?oMY%ywLlC;%lzGKWR z8Zd!@QR=%S1eIp`D4hsqkg$*~xDCB{->pHBXwn|)$WVgOkE>j`6La~4@!?ANzpWe& z9Rb*dI0DuRFjhQXcExossjA)bwdrfi*Uu(W$_Qx@{Sg|CDeMphZ%bC9)G*>3CHcF4 z$3N@5s>uE04V-wUr`-UF@8<~@D$hMAf=HCs=lFgroUrFVMkTzw#zROax$n8$ZbaxK# z(s?l4`}%p`K%_S=w$wy+3%4!RK5ih*-M{uCsXFTp-IWi?9=px|Hkp6K0lho9uRhx zf%(rVFUDu0Yp_TO`8LS?61}dB~P=`p=D=jqmuR*OUDlyu$%F0lwN8eT>k!HiJ?FfXFK|d2F^d(Xa1pMgy9V0)crB{$EBZh4QQq!aiZPM0B05oKG2$?F16= z&u=fv6inQpEL~8KR3v#6#bVUZD#b?#5u*j9Ql7k*GF7>B!p)+5FEVpqPD0|kTa=0T z>7wIzD=QU-vAsTb0V`Pyxnh*~jwDC<6zj@9hxz(-V}q4o;lqvBukUHC+zl$)xMY^} zRzbY$@fa#F_ej>^=M8{Si?_vi&;u_hXo6_4+?Kkrja3*{62?u&d_r5&KfYv2v1-yD z`J-(Nr#>M;1gax0)c*`BPJ|0U9!avg;~9OVY2%0RSz7eI0ie9LZ?VpoGhX!m@)Rs1?LGRyB~d@##h8AWn$r73U_8cTs-gk@IhmaC1Z0eoLlJFee za0P1Z@>bAaq*~7)M`;Py8agQeE8TQx5x~6{o7)iqBuK#4ZP;`!@aUH6hqXm3Fnzr` z-=CU;kj$pp3cp6~bN&N6_s6wGg3635Q_09svj!kF#kn8X{GBH~jtnlM=0?PRE%g89 zO##1PYdEj~dk@5Gi8S(J*$JGf-fwM+cbNM*WLp6-d^VlSp*(zaMKe zZk+I?9Ctf=qvLR4ggU7tv8Y6&eA)gN%7e%%JrWX~s6fo8Y)BeEXa>U^$Q(Fj7W7Ip zkQ&7-d&VhA*W{U}M8`;7eoO_X_QF9|U<~NaeApL%Q9OnGYgP>8rF@+;vj2l<8uP$pfg> zFmKt|`Q?mS_@M9dB%OFZ*#rSbr3> zM_AsC!9G53>0Uu>bV`@$`Z*UL8SCQ>O-czWotX2fFiJnnc24t$iSEF~C{eBf00^R& z6m{|ngdaiv1_0;x4)O2B^jkTmr^Q0gK8N;1bjo$a`1Vbg`|`&qkjTv_^iqGo-1P?p z>_%+vYrzj+qyouE0~10G()*i_8C09=u&&xs^N-|daw-o#N-F%{#0tfduq6`LKCKLn z`T-ZGAX(8JQt>wdpJN_*$jA27*B)p3!KXEFOQMl?kGe73*E znU|mpf6=lTm^}wD9Uwz|dBdXxR9as@4Weme&*^imhmi%TTA9byUDrYK@5%AM1W$8d zYMh3!Dt_yf(*q=b^D1aH{h%dk#q~rIKQ0%1bEK^cJ0EtS2dDd_ za-st7+CCTM;vDWWI%mkv2@z4Q_r>94G@KYk#i1x)8I-gx)w`$j0^hhHll;v5aUh8e zqu}9l(Z9q8p{Vd~0=S%DAge14B!&HQ^K>0uJhMi#|J%MfbR{VO(O`jWTS<^BBux#CCcu2KIJ7u;ND49K{4^B@^|^iv1ZLgq7nvUXpdRjK^{RMyBmQ1$`ok%Rgb zT}qRS?0VT})5c?7(E^Rz{8Qrq38h{PB?lPM_qL>Uv6l=sQj+zFD;=T&*5#tdLg5PY zR8rmUWi~DhJqICvl9T}huGk2IP%@z_rp4$&-0a^;`_+lO{@*+QLj6Q8OEp0Qvq>!L z?|ey_R7>Io^ZUNE_P(7gp+B03Kwx|m*IxkK0dXemc-OvdSxS#!A?Z1L_cI@~WKRS2 z%TiuH13&i$;Zb!cD8BQtZpvd)!jD|BGE`fNM&Z@+qT~iup@)03Na6Cxt-m6P5YP@_ z(t_kXX)ye+b_b$$-s>85+fWE? zgul)MNz&Sg0=j#YKQ*MEi=G*k_SsIQAiUCa`rL!n`&Y7WFnfD{tW3b^#h+n<%}z%2 zVeq34o>g=!$R{pPLHqxUn>&nD0l=LF|4FR8wmXM*gU#nwz-0>&!ILa>P6M z>hkm1dr#7n+CoV;5=eK4hfhia_sYSl18}R}3eG?x)Ybx2HAr_n4$!Ben1)#h5<85n z9cMo82v(iUKP02yCshR6B`YZ9wM2i#!1O-*Fg~sT)t9-;fFX_+Q9q;X`TE7_dt^Mb zhp5-A%Pfb7s;^lWpX%ncbr0XrTbSp#aEfo`15?oD7?J}5s_7qzE*{sz6l2uBtRA1y zMx!rz`D-w(F#HuTgKjCb&Ia^VZ5{=p`PT(7?{__~hm=Dp_>*q(>C_&LplAgyCW>|eC6y&Jd?&&kH)vg)e7yXhl#H*XLc+5P{~n(R2fr0 z3l+PuH_T{s?bt2(ekbiv$xc*seYCG3)d?C5n`BLfA)=(f-+gQPlaEIsvg_{3Jn^+` z7{~sfNz1zv(56e>)4bJ|{jit3lz3ZUkV5oRf!C|^#KOfRE zCMigQGE9FrZ@d9^f&BZ?MoPVc8v~uUlV<<`Q)IE#-}n&cy>LG%qGL~@mPW{o)m>WP z=*TOAkdT!yzxVN*y@NEGwl`VvGAOc%ZUX$khu&KH3eUkZPgf|?wC?5K(!(rMM#S8V z-=YKAzKU!YPn`#r!?(X~LxZ+`Q^5~z4AWx%dEo(<&J4(0%>10VnLX2t&v9mJpIbN( zyVpef?>$IOy;~gHp+ngXZ5MzE6+x<_U9Zd3*Ezgh%g0NgVT7||t~v!9i_Jty@lujN z!s2_B#G`BGu7b38Vy%G!wq<07zn$wE+=%8#GY;!{2*4vcy*A3y2aPghL@@{F&b&Ns zMYvo9nj%$D^Z=>&(DR&SuLdTV76h*>^AI{lABTeJ&c~!PVRpW7lO!z|D6#UwaA`BE z2J4J@&Y+T)hAgq{2=m?kC{)>g&%}un!DYyQ2-|&M1~?XtUB4z$3*QA39!@)8T4lcr z3`oHB2>oXEzz~;urTOZ3n?3~z7*Dxd|J5y#CMR|ud|uc87%yC6>nEJYGwC<+;)b{( zusft>w;B^pK*I1UL&~3cznR)q?8L5oT~LT%JTC6d?YJZIX+zmZ#GeI}->cg9Q4~4? z7F!YF{Al!2B&fgc1FWzJMqR#lGhB^k)D?FwP+VST)+C?`>R($sw0n_)4G@JaqqFazRb@@*M+JsFo7y$iA^i`GJ*jFj;QQ4M~i ztD=t)aqQ5lGik=hFZEf8b%S=5V3$IY6crWqx3{pTxgf=?=t>7HvJj$*5x*tT@_J9%Hutoi!&^7+QplfcV%ZaV0m)kqH zsa4m&!Q2)Da;eF%8B7B$)}ri3rll2b>*xUS2G6@O9q<+B;3nppji~%PSiCpE{8gXW ziPk%*ti9gsVN-#GS1H#UwcJ#x$H;IE3_k^dKUj*s_wEdjuQb|jy}Qqo46~Nd0qImnPYV8B9f`G zM;yEvYF*5(qi9VzbWYri-xppJ8hSCl!5lv!&2BCfw6b;30mq4gEw{slj-`6bQ;v6o&G}*bkJd|~1yU>1%X9eNm>2r_VHYHI)R(I$} z^K+>b`zk4fx)->y?gP9z@i5i}%XWABr%6*qHkPVG^};2QyS0SobyL+=9N5uc+D1#X zv?J^sHb*oU+^Y!QF|{wR%HjgJKY*xkkOLXjbr!472!tPE|IOOQD-8LzGj$IIRm!2G>=OYiezRDhSF48<% zg#%kld16man`SUuey31A{4SJ8bvU7=Psn`Jy<>cmqfWYFZO>0{+@j`%EvIR(8Uefr z176r&*#(b4lg*!iwSR;9y^Bp>x<`2#1&tx}e}^VFyH6{Ywx|a{_r7mg-<8o+c$rrM zPGGg%B=jRY;d3R~pqoB%y{;K%l2VlHE?B2N3&=g8U>VTr5FNw@+HFnGT(b^%2Ynmy z%ps!6GL^nnX&jmkUsi91-wr0|v`f?#@XL8I|;03KmWmY|bj{>!^1G+9W&t zx&h<0fkzX?=`m8XY263B`+?$s)+hXRLf5&lucv_KC?TAhAJ$vL_Bmz_DVrCMewx=0 z3B?f6b4W8DT4Bk8hrU`5yb$EHE~O&E_}A?(13X*9mmxm?ve|sxRzrl#k-H1Y(B|$NT2)Pqc}|B4(-|(@MkO|Q7d9Rq7wNr? zjB?(C@{jf|?+Kn^Q&wROr;$(UB(hQTVZp}=R*^k3?Hp#UDQPRxn%I0Pwjxd>T{~%2EJ^xSfw8A_DC7$!i66`g zXkRu>`s+39H{{sROv_e&NE!qGe1Ots+6ApZ-I#IAWpdlaWu5vAD0m*P$f22z00Xfy z^2*{BPkZ&!0(-5iB&~Zt81!*xPp!dJ86MBaQ4HN;^x=J0db6Xdt?$dZSADM}m$YH( zp-GMs2(e@|{kZ+EG!N%$48FV1)PR82-E2#L zs@+e|dApCRjO3xMvvV^p-GbR|Gc)XD)Nffkgm0q`Y_HmuH$EDX!WJRCM*Z&z;KN3qq(EAxU{;q(F>Nu{mY{E< zgi!a=A$)%rYkC^tgPp`z{_@@a3ZExT`GB%(OGFJ^e_!Mg8>?vP)0VKvP(CK>ZR}^d zqtz|l176zapalpqTXW%XaCX^C@*YXV<;ugiJ_Z8Pjq62p*t=_+EgEslX85+reAdjg zb02%b8n_I)jGnRqE@eYj|cBiWW%;5eeUqUvb6<&t%8EPr_2{&4YY zHpnFAbPg89Ef-q)v*Qc1bvC?q^b2&g{C$b!;_sW>lSApjA1m|0^3w3X6l%v%WY{V) z$FYCw8keqVK-+~Tp<&1FG7$xv!%D$*Zd!j|^g8aM5pc6j#xF-lm#~RanBMxfh4bln zA&)RqhWgEiIGFfmkPgr&N25IQ4IJMN-e&5IE~NFKadntqc%}2dyF$t> zR9d|iPv}&U7T)9Y_R7Ivf%I8^b?|#$9!PVbaJoL~%%oTV0@eXu?Up^yUmKjuK zuE4S9lmD||;XckW&;0F}{{VEpqXwE#pG3VOdSV8@nM*O$RJ)oJ==)4vYf`r>my>Hw z`i7V_`dKOF+@!Ig+*0HWyf{q5zI^ROlRBz2kU3~05zqntnNB2H=}Uvcp%*E}x0&vq zj^TxE%?Q!1EuuZaj#Z5@S8tP9X1AXEQInn9vgN7C?ANdy7dU>XfkL56WzO5_ROwL4 zcqS%K=j{9|`h-GsP$6@e-kRpQlI_Mhs^F#*`P%!T21y(LEZ-#YTj2VxyIL?`AID6A z^EJGXT(3<9Nr^Ae7_AL?$xy9)+7isA@*@8E6gpjq76V{3FVIre(^%YA-mKGYX5JmA z&Q`18s0u-jqBCx!-#uvbT8U9R@Zcg)sVDSyq-O6p%pkoLJ-^%+>FMUa?@GF&O~jH= zprO=o{cUn9O~m?Ul-E4ucB+nytiG=4qzWMMaDR`)JXM$+KsL1*R zWYz_;?L;bG+I=M$zm-Ad`wj5G<<2c`Wv&VWD#(H^N?R-#2%!rFU8!6VYaioCRO+9< z4Dt9c@dN;=Ez!!}f7GPsNc21v_3XMvzS@@5i}`E~HB zk%uP-wfmY}D(#b#TQ)gHVY7)kFkJ*5p}47sE*P(Qr&YVo>F!{~(RmQU64Z^njIfC2 z_1*emepnV!Ab)S@2;8DQkG*(ZL9v$d)s)3kKGjHy@!kGQao4|m=cW#n=C|Cz@7n4= z_w|xBL#rH81Jg}XkK;)k){>5~+x8J^cLu%r0h#cm{+lbX5wXH2cQ_%+Z~U3j4>U>0 z@0hhY|AplJ8>;2C8*0#07WuRM8Uef!Xg;bb6t60S++2`xgAdED=D?)f4*Z>bFkyJnC#mlpK}dj-dWdPywS#3BKzBme)hhIQ z=J^$b7a+O$nZ6tj-Sp;)DrZ!EU}DawCAr{qcaMkjIjm_Y@WhnrnFRK}w^T?!W}@YS z;3qcbpe#8d%c6G%~OqfUL78i;vL1c02s$TO|x8>G*7f< zF@KAC@C_rxMeC&K*J{DNM&-#sSCNg>=bE{R4vSv>}c8jSxTNJ zTrWDajEUg_9sx2q8s z@v*N}{o%4f{SG5{4?3ss_CZg9_(Mi|>q0U-gbvDV6wfP1`JRCZa~UHBA48 z?ySE!VSD()Ue#qL(=fcVIa~jZq7;F;@Mjn_721aVgBl)KD_X9({B-JqNA286{!ou1 zB~c_)>$to1dhJimQ>=8QR(xTX(^$R@Q-qcR^Qi|~~>qX!6VS4vS&dI5$NvmUu zNo3iU(5L2R+tQi`i=Z#podLnim?Y@=2E=;K5_l&XIC-LhXJ%@q!BoEg>k&{r)+i&B z#Ww39&oi8WuAYdeao4NsHk;76UYAIJriFvuLKF|=F8M)^%g09jE-TS&KDAiWO|Fd% z6SAT9;;!#VHl4`ny(!6(A$){KiFH&1cSCB&C9PD!)Lx#d6;hZak2D0)}bAijMdZI_L-h_GReQ%bSm{! zI274QjyZidb&=TdC)w~*WGB&~ogo1|WJtz`@A-?m6v?HI2zyaixWs@@H2gs3oifb3 z@&%6A*p%6FOoY=f`l0X{>7%piE$86RMS%@8BVPQxJ}n zmA2?h1PsoJ)vGm2Jh4f6;>`>~az&It0q)-B3d(SvtQG)+a#00m@B99hPiw5LLVN7X z5Imy4$~soDM#}Zv)EtmAEhNAGKf*VGSQgNtZxLd|iWeG4QoOr6kzTf`R!wSQ$v&T5wP>oCMuMF3Edex*fR`|{@<4kEF+jYOjW`$BD@F3x%7be zGLD%7h|zDv6z>k57VgiyqlySvn~ZxUs8YWQLntj)J6M>`9TwoAi|%7{Nb74T#B_ck zB?FCq>)V3!*FgQj-vYF{ zgq^a!T@z3D784U3&PzI`{?u)O)yd~q{?ZgsC;^l@T<3615s$05AfQE7X#fe=bNcxS zS!8Y`dnc((-&&&1Yiwo4ohl*c{&RJmAZJPB;(63@`ENGAbge&*ha2nF~RF#C5i||d$XxT_kZ^!HR8i-CBPXz&& zfuypX^`7mFxJd;ituNvB++)aQ{>NDLIeC&Jhr@wBHxnoKCxRp2Y3PY%L%g)@wmJmP zQd7P6T0`eGo{&!5QN!&eQ71T~|3yRZhi;C;ho#4BIumarpJm1L{0aj`?JK>x6IM$us{@3%t z8bR;^tm`uC?##areSFpk}Yn??W3$cY`(->AIaBH43_m zOgF{66Xxyu0*ntm>;alf72{!eP}DMW^)H<3Yd6TivT8va1i1Xmsm9O%7QxzC;f}Kh zUa)L5IGN+LMmi{Ide|YV3~zAP<9K(=LfR^fidA9V{(gViRN`y4ovY0qq*6}uS48ax z5%tyR!y)4q=OY%tgmf?(ttnyCQBEXc2LRVC;hI*%xj(;Pb$ zUjRtU9^CxDXO*B*Z$v74rg7Y?A@{;rOG$6G<@+z=W(m79>PRUxpY+zQo`N2?ci2^a zV_=r^Z1)o}U|>KVui$cFyMldY3040$Eyug!NNNM`u9U~(EWtEySG#b46byOUIHF8~;w>U-)s;-JU5LSsyaKfhz@l9SQ_kAzoK^-b3C5hCTJR*9M5ph+m|?I6YNTvOh6o zSMzCj{V3m-B&tYAT<87}{+fIJ>n<6D==iIUANn8xok;gocMvn!L2Nf_{p9Yjz1Q8t z`{6h0=aJhXYsfo3zUO_zL51!!{4}s`H`QQTOn=7se=8$sC^J9jdo!}ywsKHpM^})6 zsiPNXkO9~NhkO|2z1wzU@XhfwRfL66+w}DNW3+ww)CV+zmg~ZoEs>4uk2<#l@qs-a zmO1^1yq@ojCnEpeAAbEeAqylJ%{e4ca@$#rK11 zm@87>?OrguFmr6bs`h!RqSXs7R~APZVkRd?FhVIu8;!@xYNE`-yFfMYuKl#NnV*P_ zfRf}!n8?K%`qgU1qG?8(ZKW~o8f!NFu>wiK@9io~U)o)7t<+99IUloaufjCoUGIfp z54CrqAxWdeWnfJK6QG zLbNgd-byi8)43s*KI9~uj#STuu&4uT_7QZeOe4d z+G3zCAltkh&M~a;NGK_Xboy2}^(j1e&a*vYx}x6~ndRZw0et8lN+|dAEs_+LNA~PA z4ES*YzH|&Oul1o1+|GEqsO6KB=eNt9EZga^q1%#egHOJf{-|`$Vxcw|y`GI(_%fbc z{fzi5{%r~f;^vNv6fJ@<;QNG%qjurH4(OR9=O@LN4b?|mN(I``t!4YY(BMe$`){$lCu;3mb#KuF5^ zz)r%-*)BBZP#^#T_p+hHtMUz7d|9=)(B$T`IFbuZVtg0y?uZ8dQ&T*eQn0mgB|E$u*H*O1FGFW<$%>dSd)bFoT-X`nwBNMqavhpGf^)8Znb-(_G?o?-Dh-&VcgObdUm{ zW}}IRri^;;XSY~z>;rznAEN^*K&IOXDQMdC%oWC0Un z-}QsxkVPf9*vl2}5qOK&jHFYJ@D0PHhjYDACX758GWXoXUM!|Aw^$R2+u!D_m;+>b zp0P5N$)=p{!%}_cHS5QGGKWb>F6ix-nQR)m;N#)ZhWz`cbW@BEi3?YlLKd6cX!Q1I z)gv7x1Kd2&S`1c;)b!C}9$$@COi?LAO!~T6<5_kZ!nvEd5=H4yq85^Q8oaRHQDk17jr{TgO7X~I)D`(z9)=*m!|SB_r$KQb zY$Jh~gKY#L?jZv=w=447i!IaDM3$Y2mZ>Jzg6~|{SfuPLZ;rUtux}z}8$PpWv3H@c z2h#+;$+)fAd0M^EZvW`in1F>1%Gq+;ZB%$iVmYBDABjERqH)v{JnFf;cTipHI_9*{ z4GwXr=?`o1XqL{%{drJAx&7>xzi+J&lqO`A@T_#42GXLPG($DcsOK_F>s*I6%Y_%w zUDa29$lY2>^!IhXMb)T&pqf8yIR*;L#nAoCsp8pM3nT2h&{*%g*3uSiUU89Ep( zZm+xTfrp1@I|=deNbfaPD%>Q6*2pw|A1-(Hl&c?mPe;-eP8sNSs>y9L;JJaQ;n0?r zP2X(^X`ZFvRoW@4pDU`IqT&u?!p@A3v~!ScB>NnyXtDg2_6~!DnoU2S@o4*g7^0Ua z0<|jT_T35NN&t3u>rZ9=`W;%cMnENQkN!S?2I6I5#K}3?vDj_sy`JE0qQlwXAsA1W z)%+rSU^g<m zNz2XX?s95kJiH6sf8L}kVj_SpXu#vZRb7K~KpdFI^(&2-Xc)wLqGaud$;I!H6B3!# zBSeuOpGQVQ^O99?9pOf^jzxAxh*(ehO!Ny`3W zkv#_`9-hDh_j*{O<&6vXmJYv=LMaP3cb4N5H4EH?Nge0T<`OVB zq9*g$i{(@u95lS)fA7Rqh{k(#^-#}g+mEi@8oe}ph7b?$?D;?SSRA?bg;aj21}>h# zL9>(qtoi%hC;2OEA*g2a*miBr48@4eR{zbKeV}qRE9-`#10H7}XCQ^ueXz#?TXOaG zQa9fpc4Zq)L_>de94={aOcMDBRwBC7HiyWU|M#~P?Ux*1uO||zY1g?8a z8Zkt_aeVJyx4Yc1F2aTq^=|yG%K7evZ--&6!P!NWd))(pCn-r~Jawv_!@^57e;?uF0N)MO=GB_Uga0juZ!|SM!zsPO$x#&s5-?N{>bj6!15bBbj$%k*@i~%n zB#+#3fvf}NXr1I2WgB!Ej4=Cwg7vxcx@UZas*UYGM{DdzdwXnDzU*ML@Y$3vPxL?) z_p{yCFen@))5sf^%KzUYLrVs!RSc?C3^X_3PdpxQv6w-qr}P;5OrRa&KKipQMc62r?`@66Be(;hZZs8QWOuZ2`IvVX!$K(BeV?i$Cp!80@rWuHxKplwwvk zD%(^K)m%3ZhQ-z_lp-T?>h=nn4(k$R@bErsPW)#RaFOV#uG=w}#98LWZ7I^uv#5Eu z{1B;Q4YVA?3m@+6Y3qb99jCU23Ov&LG+s<3m!XD&7fp9T07KKbqUZDee3268Ko|+7 z&unhKTTG@nxioyd8RJHPAK-zSDCYFj6kI8cWTCEbN4%6Q{w{)9xZ=%Dy(=gfsrp}_$dXOEH zu=f06B=vk!+GkQiO2-nlz`%QdAH2x4YkGQ}eflB)PBS6lQW>?J+!JFQaFM^-1jQ(5u! zmP}!Z2FGI-=I;w`p;N9t`g09lPs%JG`pnkqWb=9oo$$!}~|Yq4>l9c7#jb5W5W z?T?;1O{pgzea=k&dmUYzer{hC3_5CQHoa4i|g`NSotoupQw=YQ}-W;00%RgUW`f<^`pO{X@#q%o$U z8|525*`L)S+0Im zy^?2t&vG~V@_&&z80A6Q%3d5|=4h&{IZrhYv6s`7fZ!OdgE{Rrg{P+^+LsFNB=u&t zqVM!@hxZ)U*?kap)x*xlWG%+5+|A|lu-{HEL?8XMt>#sS9esqPu>2eck*oMOujeF> zIB)@mGElHDnwoUECIWj$FHu@)Up-&Z5wrY!5=Tyvc9|R-i_7G`elM;yK3zy>2e-Rf zX}U<(QW_5CbdT#ihiA(Iy%T$f2BaTkG^KM`nQHeQOXXD|YzF0RTfE2zbv)ECMW-o1 zz+4}t>99lgne+jrxCzen11+Qs^esZyC;$Dmvxl$V{qePe(}mqqn5A2x)yH|>K%U#G zwb>L$w_27>&=S_B9oiX9R@-P~*0}w2PnVnbdKFbIDxVr;1LS%BzQy)u!MUIRb?##H zBpBNgo)lv*_mt!%3xPQZL6GQBdc&D;Jn`j{Hq?NG17JD76;>VMvHor(MJhgl>iJD6|W`Ij}K z3V+{@OH?1t4jO&(8+fJhT_Sp? zJN3*L8(*|~WT!{3csyCYf{d3Nv<{EQ3ePYUPxUl zX0P1;ksSg4Us!A=T4R;?sBLI~Vqxs=F}4EJLBZ&`9TAfX72-SviU)o?DdS7@?P?uH z0lz{R?$4VGP=1KMUT|~(b_zbZPH?_aT?hEa2+aZs8ZwA^zOU@xPD@06=1&>cBv$MI zrujzY%tUcy_sXF!#3$vrc%|uOX6vh{`>JE{b^gYhEHv^A24^4^=%5;${j1w4H!7BN zM{Ux^{B!EmsPNET zTMyKl_c6Zx69%Gfbc%X*N^(5?*}Qr8f81&FUw3+8!Xc{~Ki_k1u|>Ij6?x@QHMg&+ zPV(AAG3#keYaY>9(PBpil={Ny)9f@7kI)*z{0N!>_f5w@lHwli!d>^l!Ln#gZ%&9EaA>v)YXT=dsmTU{~iueeoE zSJh(LpD-W&2GnRYKek1<)wL(&yQ&)%_Q#9Q_2ji?=goL+-w9A4VLwl+3)fGSQyp!e z>lIoizdp!2(&L(CAnta1XlFjdw!4=jH&&axxD;-%Qw^ehT)b~|lFyBF)#mz81nxmh5~1Z z`VSIo*ef?ugd(Wz(e_?=Ptx5^C8pRDtHVwUkerp{{3MfImlgUN6=%=Ac3%ui^WfX# z`bW`O%>9uh2R-T99KzXT7t2#vx_CHTw3DJXXJ#$8Pfx7(7g@QbM`H`E{*DJq!AJa#FC0)@D4kMV6 zbTcc|&{T~Vg(~^*-jC(k(9GlEmD7hCWFusvMPR8<-0HYKthp%C7Iz3fFw7J`{8D{B7bF|TS^^gWeXT?mR~lV!)fX^@lXmp4T(za$8BB;R8e~kx zzQuV6+ex9S29iQ?Cbu7~!_9t|kG49Fo)%5rUscURduI+OX0&F7EqK~K_E-uCw2>~% zJ~kxb)f}E2;e+>A2k|}1@cUi!nf^F(Xif4N)FOzO*mk7~uT}o6zaN=Dwo|!0`|@$A zmWLDYnL~{|5frJ_mu@E%1^SYhEo2WC=zfbjPx1m^BRl-Z3t6MFjnYI~36<5mkF0sT zLqvIGK+YWIQSX=&P@h}(*pmyGxwtsGA{JK_h%0itTD)oZ!%?3;;)<@z0$l`snfg`w zx>`G<>ezG-?vF)A^d43TC3db1JsD91q}?^7-(-s-fAfT2=t(z!`3yQ(wQbT=#6g&< zRa`$Cg(O^i*EW ziOeY=4bb+rnZU;ospZq=Cbc z?`ZH>A7{6`;L~Oc_dXb#3Xt}yC(9`im)hH6Y}t1}M8`SgS7 z#+RX{J`pSG&um(mNQNw`&!2I8~T_PDW zE!6dNtG0}dW|U&e-R?N(qFFROcoba_{-wFv7Hd09v+~02-ooyh5Jjm(srllEW>9E| zYPI(0%Sb=kVLDa*462$RW^4T(8SoCsXDF21fwFocLZi-YY~Tm9l)uafcZ)H;CZL|h z@eh4JeIk61w-5ktql{oB^%(;E+-h^yna(z-vR=L z7C0IZMce%)0-_KFzYI1JNl){Q@%wIU8unga$dH;zM0*Aw!|mehu2;_0eT<~G8y;Tn z_e_%3PqoU%z3~hI?p1Ob9(}XH z#~0YXrsy${sE{(9F9Qj3*5Wsy z$XqVokEP>pKd77- z48D{sL#C^#1*1GB5(vIl81Q5vM$-2&BDHBu=-_`#8bx$XQB$OI}uG!Dn*RVB`E2R_uq~U=whEI$0ZdPuY0D{%(L|d8Cl9AVEXVbgk}XWuO88Z)C`FKr z%{~wb;S)bhr@&ebE#oDmETtI3&(pt<)r)Q?U=EO9AGIaP%XCQBh{ z&RTPF4wLe9k1SA|0iA0B6RaP`o^Y@~f&N@8XtFFl`t zpl@=YIN;27>j+$SE-bw%voW%Xc0E;AWL2NE5>c}-Ar!f}Dk&&7zk`iv5LubA^J*9x zpr$TuP1{CO=oBL6SJMp7bV`E2=&ZC4KkCEtZ~`vUxwbWR;qDpp0EL90>*q{6*lDA#T@?_4@DXiOA=@nU7 z7qXnbm!hC>v+{M1&7%1P8 zb)RBi%=$*~j^mr{^8GQ-)|?|j7mg%3_0gA~iXLaI(7Y`R(_QSe$HngtL?oOcv<~(h zG(9C1Bg65UYg0T(!F+?e;k6Er)b%kTU)GArY-6>{+l(AGxmxV8D~mHWiXuINCA{{G zsUSouN;4j~B|B*Kj}WyQgs6Co3T|}jJ<&B5=70gLFvaOXsaB;K2qP3-vIOr-qxaFS zW8JT^)1~4WJi0j|OzrlcI*sI_B6`bLqP&;O;1Q8_Xlb$Ouv54sJ;C$&%U6#~ONHqVbF)Gj_3ceNUdBls67_~M>%X<*mpQ)p zRUBg4(2+vQJW=Y98MR}>XeObt{G^IbVDRRX_axO-=ShZcULQ`+S>_yS9wmn~bSSiS zWotjhs)0Dh@U1ea$cq?2IqUa#cxXbH8T-&lH;wznx~B$35WTsu$NAoCHB+~e_9CY; zd}cCcY&+y0##!m3)}n2P95un@&}~+lx4AgGB#^b@ydFJ81bATB!dH*Fk?bAbyF@LP zBKFS1G7P6rifN{XAhdjz=(ML+UHcSQIbkj;+*o;dUsd{Ap~(^{(5r=)+op8=9f4NB zkktZ1W(t!0`?(M6V8>YWl0oLFBWo9{CFr7*(e4Tcjn46Mgb#A`#yBgD!nepiW1425 zM&+oVPowZ#+mro$jXqNkTaBB(2rqhpD%4bwHPn&P@S3_&x2QQ2U_e5^=l?)PiSykk zY@%v@cdu}@2Eku-6wyJ$E4_1i8Nx1#M)><`OFliSDSJAbOz_#g%2zHwRMufTE%2&6 z#t)rXuC|*7aIBpgyj2BeIyf)axuIfQ_MMJQbZNO#A;016DK zl!|~fh=S6c0|+PxLn+M=(m8bJJp5##G zKqAkyQZ&0am6)*w%nmn43QBU?VP{}FbtVfGkBktKP+jld3>fxelKusV*A9eB--Lr9 z9Ay2R^`g|XUIfGz88U}&TS>)CN=P$zu-wWXa=7nMV;pdG0XMGO0Na~^U6WioCwbF! zXIVwF^Re#HZtpB)z56o3A_b+{b8LPss!B+nrwv;8XLrYY?@YCRXwXKeIw{vH zS8+PLIZyNT`IZfzhhMB4ZYcXJwap;+7}k@7hPw2ON07PhMgtM!_*Onb-nZw~9y!Sn z|9XI9-_PV)!B!8yl7aDe&6cUK2Wqh;-plAwiAYT9atIPK^3cD+I}<5tGK?n!kuq!Xt8h<&yVZ6eBx;pp)O$c9TDK88A^>qEu0zQ zz4h%WNQKs72q`GpPBm$EaZ%=)0iS`$zoZuZi&RRPST}^5P~4Z>oRs*F15)o(Yd&U_ zSJxzRDP}6FUE~P#^Wg(Os9(cgPD(7|r)(7ykc4r}nsP7{W$t}&7+&vLKuB8RDmmzGL4eI?l@r5w&^d zX*T7=Ly&;XCj`z6s@kXHsH@h$6m)Q<&4$;u+y_;~L%T7m1?&bWJsN=+?#A!*Y?E4H zv0oV8#r6fn>rW1450x${GW?^JXyh6+{)M-pFK4^UKSKK>m3DVVy^FlHZ)WOAp6o{v zX_m9}0m(_4xa2AUan6f{N;#TJCe?A<^)WE+SS;j8W);%(TbU_q7^=8Cw(0F4XDavks>P2))!Z3^fwwSahQdR@Dx;7RM`K9(mJk>~v(khxUW1=ifcIm8CXYZIX-?56` zZYxr?)=cP&47^p_2PrO}N**xqF8D=LYhn16i*fLM1c-)+h)AQrp7z)L?khG5*|~_} zffvYOi>j+fg5&Q49dhZz2&%=ov|$`f2i$5f4hXjwy+DNI=IN|#*k!609mzVgeE4V< zsAbSk40OcY;gWH( zg_f0so$eITv$wqDNr?knsuQg)wZl(N6d)X%=U>bf6AF!)Jy<1PFDDJeRvXf$7nDUY zdBS?q)egc!w3wh)aBSA4q{Mkj%1KZ#-z-;hGrpw347qVCa3QFj#m+)zX2Z=(?KPA~ z-L)0HmLX4qviDdj@|&6eN^33GRW_YfmGP`uN$;MF^J;Nl?rX)_to2c2oP)f!EjPbT zsEL%Rn`zR3weZZ57XMKVLIy@ob2hz?clNRJHwBAO+sLh-2KNumM+GIxXd)=r&4q`R z@$+(VR+K}20_8fGAn~a=Qn~8ICH*s!jp?s%$ez&BP^hX;(%k%Pr!%-ZpRv+-UXzTm zIMtbaGG>XzZBRGF0&ewC3ZWzG&Jjz2{pNb1D9^iwC|9!$nq~V2epRmeaQnRZXC1e91u}Gyk;t%*^kVa zFW0TqI&++TFflL;9b}AhW;ZbFkwZLV7(u7S-(6QUV|Z#ZaDqWXG}c*tlp`9{C~BA{ z2{A6w*NgldNf$4-L@K>j$~o_G9#Xk1ko{i0ibXxnB@rjl0!+0eJ=H1np(~pDsKkA1 zze((kbAUF(kMpN1=z7p&p7#S7hu%QD&7E168v|Bep^|Mi5LNXnGOtdhmXaBm&$#k>??G<6^2jS-7mK zrMm7i>{r6l462=!8U|5<1+(aQk{$2D%A^+6m=+bL>9w$qB^Y{MOvO{CDjhFYySxo# z!`}%6W-`j)z|o=dc87O|1_@J>>SA#Q&=AY?WAV`B_+0T5PB>RO~O0V@{6_UUBP8=0E;+W0z9c>d&5a} z91T_ZpF;t;u0A=hy4SIu(+qYIu^Z%e{GB1{3r$QR3Ef^1v#esK2v6kC%+!)`do}6m zc_vaHHVpxhH#Qaq7!WPsO*wkzRu;r!I)PBtz$RW`16D+rK3jv)r5L@=<%vu8PvaQ{ zkGvcK?LzQ!A7HC4!>fZ$VAG$jr&lw*_eza(N)FcU8^EAIMG|PxJQ}||X zKD=dALM@H2H*Rvnjkfj#vej~57&B&kQox<5`~pM`!gd0pXY8nx4-5VFyZ}-P@Hc$N zbs;N;y!~l`7gs=W&UH@Zm~vMR21)9SuZsyw@IgEEM2Qj?&&uJWYka8owtbqS%y z)W$1dw5L0FGvKT;TBjLgUiHhH`_HnDpugM$U^k+x&yREwkj`bvQBq&3y`ANHM*Eur z>5+N%3IGxvD9?dvHy!yR&gdl(-?p1!+d|cSiE?kXeEvem?&AENB&23&`;AAGwfB;4 zKY1RLnc&sEe!-&ElJg^g!S;I}ndIOi!Y_sMBDm>L2Wbst+tXxf^83!^N%}&^c7;Lsy4^}6 zoxrXG#X$2!c!TnA46Ai8u`r3Y_xj#}>eNq7*!zw+`!YB$<&T2Q8?)j*v7daz3eOFR zeBN)*D`-ZBLbb)iZP#qX@$B4iO0vQxli{bE-?=`7*N4hAANr#bLOK^j7K}#~%GUtt zYn7y5h4fy_JJ)xbr2ITN1V;OH*zS@mCw200Tq1-{`?S>Iy;PhnJGPRu!NI*PyF&#x z{v{58VV9GB>k#f{Ji7a}l3mvDB>RkOHf0OJ(hob%#v{gpLp4LPqqe&L$GuuqB;_oB z?+tLjBl5A=ls%*jtj`6BVw;KZL53*MGgWjDuSW78M%xBuan{}lq`V&jS%e+3QJDEG zWL_!3-psDs$Pwu0tvP`$yxvA#16O^w)lT~V82y#MPX&aaC%^6PaR{eNzSJ;4jrE!}`kC)2T~VR;<`LWCY{RNVwn9o|6{>!?B&^{v0K#A^+H@nDX=S@I+&z?sv;IED zher7?p<_)*#AYPE$^MW``gSZmsEhtSSk~^($^P6;va zcwYYxHtOYDSFr6Hm$=}(4xdFD6A2D27=7x!)zT2Ll5W$ZuHt$9W#2Zg!FLi3IWp$Q z+RH`9_3%(ikLo^DSawsv@?kxH?6oTX2!hht@K#v;94PAH3OkwQyv0u&RTcdLREL{V(w#;UR&X zzNaZZ{!HY#p7F*;GiN?(oV~bJsLFlIV5M>RH$de^vLxw?{5zjCBt%vWVY^s|4FP_5 zDnV=7#qz9vMmi@|ZM}9azof@$gV-a;#8~9el>afGe(U@DST0C%A_thftrhfBXBez%C9i*-sHMtS@ z8`i$mVC{Wq6>XHNzItmxx3zi1I%syHk>g()CPpR8#A$Z}^Cd<}A#eXix|LgFSBb|@ zN3w~sXM};>M_xRvcY1QNQ$5BYYAHOyOp7!?2B3UK|A_qc9!m$4Qs}-hd`187R1T8P zK(aK&VT(A_riWwPet)(N4e_`#=TI!h?iWv#jri|wg6OMASO26WQIF3%h?RRGSvm9z zX-rNcM}YGE>+u>ATf5UoDd2E8f-TwXn}i_n?1cJDB;9Q;BUE`B#2&W0s` z-h2R?T+4>_QuyT#%_P&KP}sJ%?v!omT#ranB8hJ)Yn5f**1Pe2vHEFGL?`+A{k8bO z0m5*zL%PnNNp`wF*4E#X;&{)U^m__m8@)iZ*0VP+xu^Yfcj{nIxO8q%(iLmq!Rm!q zHeYCw<`s4WVJSGCO=QK@Yjd*Ps<|liBSF-dtS;!SYFwcc^L`2}t$FH(*WD{Bo5QPX zHdD`DjIY`9NF>_tO7K-q1vzapT$dG~6Z<{2B$B}S*_JN^JBId=i$C}@rW-E#zTH0} zyZ-H{%cD*ztR>5>y;WQ0b~9|s?1sQbLTN?3SNHPji~NW)-mIXU?NkWu3hdm?Q7GYF zmv4#A8aIm@u{BdGEop8mslv$RVQ(bqZ!MjCZXigV@h!pgz`NAgJ|J{|OER@0{GZeT zOf$Ekh1ZLDhSf#`B-qDPw$};Kuw&U1kj`2xK(wXyE+1$CX72aR+q~|+3Df8#r(>0z z66*g7_=hhVmFyAr7lLV{ltfWMbjcSWX;wOtJfmnINFAmuDS83zXzy_&b&;ET>m!Ma zMg7V0%W2$&j4*#%osUM7F-ONOca3la62 zwdI^KXw(drZFg~q$=I1a#YZEXIilOiZ3>R5nm%{Q=Fz4 zM94{886ua!Hl#p5J8qr+EaZWB8557TJ1+K9qsMH_`BihIeQyR)ZV*Tov4Q-Z+FI{( z|9J)#TC?4~s{J3Cz5v@D5;48l<{FWW+_w+{rqTfyb>u~Xdy*HNClZ}g?7wZBWFukT zDx0|2(I`|-U>=U0dOxo2rdS1Pa_^Uc;n+pGegmCroZs5x+#vN`{ReBZA_G?^2bQ2i z+&vFC-1>wGJ26y_P>w^+?P4YMxo=wQBQ2Kf0Tn}~|7#*JGR?cqVMLw&`ygafNX zgVhkxikT}6rtl*1HTABhTJLkgpKe(7Iw<_PzL70bL&Z#+i`iehyVFYQGaAS$9}x7$ zPsuI-Eb%vGeUs<9pNl2vv!XPU5>MVD3A~YfQQ?xFM)r%P^>5hq#`h4Ib1Ryle|%c^`iGC}b(^2RxTD+?Lx z^PYa1<0_ImMe|N7Q@vb0lnW6Bt=sLbIcyyfeLvmlukQEXF1%C_a<@ipR&j?*x^}xD z4xd+9cU`PYUWcGJ zsw%gxjB_;*_bPbS1BWr%kc?92=_sdoJWCt#bI3kw#b#?J7QA@$Sdr6c>)VoR2UmHy znx05KX5d4bRYFCtXFz<#Xh_uT#g*4a+nTPx`a8sAhR!nEc)yrHOBwKw*#1M^uv7HZ zS~-88Zl)M>k!O%6s=GTHN*0wwF`({i14JQwNuZSlfXYSo6QEZc6hC$X`wO+wDl+rD zLbN#tW7p;pZ=~ANvR@fqu=G2vP2;}jy_-$O<0?aThbz_lpn22zWsChmZHN6&3 zeB^8Xl#6-XC|-${aRi+T7PnR(EN<|C?Itc^1vJdmcZ-$tWl|FnRotomow5W9(`fhY zV)ELRw1MNOSZH%m`?cHI*IJpE&8bK8SLL9Zn+}|7L449}Rn9>WVq^Vw8<_X> zYTkDbu*I%)Y2W-%4`#N9-{n1Vh75ZbY#DX~%V=!1iZ(Ia9(c?@;$zj%kGvJR@?vTZ z56>)#QCT?;SGxtrly!373+#2b)ygelp5oU^i~TW*@70Sn$wluSug*2+)W|m*_srec zqklk#Y8F8&RRa<3mDT%`vZ>g0zpVlpFw+5=g% zwqEcZi}wUk%|SVspn>lZ-I`+iHPuHY;O2sxS~TIj+aXZasr; zkMHc(5fqk)=(Y&MCnY7VJr`*y^eau*@$WP9)h74`fYz6&<;_y=D9J?o`;_tDwA~?F zBb2HR_ZAu|!o{?&`l(XjjdaxL=N~xE#)86gpzn9yMGK+ZSclg#)vrsMZO}d@Z#)Ga zfvrZXCP*S#NN!^7@l7`7&V+%VIp`bwa8}geRf>09nGt!e@;I{+`WlVL8gohtnpVyL z?R`8yxq(hY^hb2Zi+SPwv;|iUcT^`j1NWA%?=;2G7b_dZ#B3!E92g;(mgB;U%g4z8 z+UwA->F)~L!Rby{N!QXo8GfT)r#yRMkOb=W^FD@U8=iqn1KT`+$D=!~7t=ZI!eKUn zPdDIWVRdiZ?6Y2QmZ=ik>M|hE$Z^H@0^|W~tWnt@zH?7fZ1>?63W^$?yg~REG$4VNE&hiUc(G1)$Q{tzP#{z1`YXHveKh z_w$fOjHdt>V5lNvLTqV0)xLx0{^#R`L^6yi(e4;BNJK*(ROI-5Za zMf?KvcHU|8V1Zsl3|}d__U6z*l3}Dl|T=+X241=m)Uc(ls?|~frV-i36D1^Tc z^2pZ5-vsN&=`|I(5N{d3H(qf1a0Qn^<~VaoJSC(2JQ(nwqXDIaygCXx^gbW%(sdPS98hdsQR;-?CtI;uE>0NqBsfpf@Ulz0c_ zW?;54Dm*A1A7;$`lB7%Or%}A<#*{ezD4*qkz$`r#ON$NP#KxI?7 zAjz(=@6C33yK6@jL|Vp*sbF7gQh1YMNm`20HmvV-@pZ}}zX|ARBj^Q)e*sWsP(Pg# z#f$Ta&2IKBU?i;pzyxTr4lU&A2(#Vnror#mJD!v(9r~GIkEM=2p1m$b)N1|!yp)cMahSyw z;)8(`<6EjR5l=GWRDzlP1AO11D$@7e|r3!;>N@H6_H7LS&`yGQEFra&T+7Ve4n3>@3TKC zQe9KvdJ33!jfKH(p&Q%k;gtHvUiF@V#0LoH9l403bXHjlkceUoAxqaV=|V_*g3mjs zv=rzFlKR`hnUxQGG&f>%va~xoDvW@u0iSVDV+FZu+QmQ3nX^IJQKi)sM27Y3#k#N6 zKqEXLPm4eiC&V+#yB$iH-ke&FGYAb75 z7T}L`lS(Y@9$S%1xqJ9P(g2pE-=+WkIIaZLycLWxV`mj%8L#)29vq(l3U^#Z0Y0G# zf&a&h!5nIN?NH05@W|}AUhX(hH~~nZ_aI$&7D9dU54TtSDz2GEz_j^S0ur=0x&wdR zCtOD4OLbTmx%m4yjdnN`Q9*5p(jxP>H=w8u#P%r1et0<%9vJJ+&;;NAq~h?mM3(=W z@&AW!K|Ex7B_!iWcn_-whs-20Bm2)a{J;N}LMF?7*XnW3{}i)~|bWYqUt-1RSutn6DXukEMhh^~uMTL?T$A;YEg(zlcEPGh3Z6CLYQLS82fCoOB zmHzM%;7@HZ`jWbh__wd2y7It~V(9PGqzV}jSrXF(SvXm{1qJ=j?WExX2RTTsyNDYUk_ zn)7Eg1{JhsH(dV5UpzlFL*39hDq*S+HSOZ1*=Y`mIX~>B`~t>7ciA zZ3vbC5XpSG1{qqql0{Ykv`==eE41Q^#GX2Jg-64~Uy-0Fe)JhLsK%CM>dDQ$SGN+s zQfk(o8{9g#)2F+0O|R5=LwJfJW4A;rT}=BxM0F#hjFY-osn>bD3gD(0$7=_3EU!)1A@${g6uMP>xlKOflsF-t}OMOov_25;UORpR*b~ z{qW2m65P>f0Ysbc`$-ZS@2etfgRp<<``4p5HXmjNi>qgj66d@)h4a0ZhdRSnb4OE zFabv&-V62YsJIZ|48569b6l$c7rY*{`K~&i)?z5hHn%oze^r$>$1Q@|3SERLYhNZBMUhGyp5*Xx&kZ$necK}qN6bCF59x>{-IB5Gt{=W4nj%56u8T-`E!LGcl{xc!GB?Ch_B z!&r`RbsIB4$9YT;caFWsN#yT^e3fMo7I1NO-s{P8g8mV5q5@J7=V8pYdyY9-@{oaa ze->cyW5Z`7E3Xb52KR@9<8y%_J-;)jNu%&j{a~dj!>MZki+v^C;^D^7Xq~th-+=KE zk>D>yZB6P!p=<>n?>UvZ-0h67VGCO*haP!0s@kt?s+QpoLFf7IVQyg<+?PvAJ`a!~C7hWobH{t3YL^>va7lB~Wg86S-kwg`sgkXBLL9gk=vD+U|b3 z)bMRPHyHG5@tb%5rDQb$VAE~2RMVNYK=%Zky(z8S!ou8P&f4Qz>Y#^`!+xz?nL*EI z_uh!?tES?-Z({8xO~Yyh=S5S80O=7g`!t-#o7pzU3u68XMq|S(%ZT|~kF~ddzFZ5> z2mLmReo~QQz=XdYwb6@+by#@bAVR|up;I)TZlf=lfhd^n87r`5=_h|MS{e0OH9lJ* zI8Lj=z5(}Z9vp0Q^kEQF12*eC;h2K#t{b3Bp)NiK>eng0JfV1NJ_0^k31cVtBO^Sm zxC08*_QLYn#QqVPj^6{edFva-I(q|K>=ZekB*g7$*!Qn>ul@e&%cpF$d%`yhSA$-D z$qh&YKH|HSrYFLogFE4o+EA&hLt}B}>)5^DNey>_x3Xk~f9gQw0T(zIKy8hRAF(eE zWe*rw{b^QyVZZ&Ge{Oo(Y<+~PP^InTKJGun6D5EDwoS8F-T37ynYyK+I)Qpup8|jP z)lJUg`S^@V$LvFCZYepy2FtyMMN0@qp;kZM(X;qv4f9yF3?83;sM3N;jE-H-^t~{2 z7PTqQ=Ga}DMhhe(})Q5oFIBequw6FB*ee_k(lAX`W$3bl74zmI&YseK+^vh*W+UQNZr z{hMae$Krl`*NuaGEvEA9%B)mHD*zLIMfK48%D_K=hc*kSn>+`^)D+k%jFz^;+_#RN zzFu0Jx$FrNr-7A#wedaUy;N4uec3`a5swdoMXt`Za)Yn4{@PWdRll*jl1Z(c88$l0 zMKAk$0#>64U0>&c)LNcXHiW8o!%8zGJoEN9qPK@2=dwSy>Z!+Bh~=SFfg(72_7$#G zWv44vRqk(;I)|$KcKuQJiA~48_Lq>FkXKME(O+@;OY;8@{&}{353%|op{KxVNhBtM zyH8ZSQn)%~6B<(o9VkKews^mH;s3*i+am7=Etg`1xU~zKPZ#DW^Jt@t`Ud{|O0;L% zo_BZSMv42xqU58>VjI=v+UeP_1N+&ih9>(3+f!PKUR%Kpp{&{oyJnVD+KXhadhd6) zqQDs>ln(V5Z;O;}Yi(N3z8APIbwTNvVS)i3EurC-F$!((2EwL z3EY}A^-B2};Qme+??S|J2Js#pcN72g=vEFUK!2v1{#xWDm!en6*0${C#_BiR+tf5$ z^UY1EY|B$xuvknwlbeB~bA94=&b;2o0cxVFH5B=vQ{~^r?;UZ5WK@DfdxL3tsj??T z9OrfhzEZ^ORIzCZ;X<+W2N(ZiY>kUR3{MLR;duyTaQL8oyzRT<^Q$|dUhKW7b!Zqj zl(o-p`|FU!ql5Gn$w^W~Pyd3Rhfy+(P%x|#_FvCJ5c#jjms9AExe-n|>S1fwC2XNI zI7;xFG=e_q&3fAd1lZ86e$)&iU&>&>yK;Qi<~MqaQ0@=QOaLWAHVFbaquqw=+1X*V zW)EXK59u?Kr%BzJ{M{d}BwY*=MQETaZVr%uE!Ru5&rro21&;XZ^qv=Y6aXby9qdfM zEWQSdEub*j1Q?%t@$l`?foa^1Q}0MjI}h2jxBq%(o;V$9Ud!npI={#D6zMraDdhmE z%bTmDlyH3$Y8uKOI=_<+_u-m*0YpsVD&B^OV-`0&i5f(m3ECb=0qh^Z{$Z|xcdIQU1RUKAi%` zXLxY6ZM)74eyg>7=OY`mwdheO20tYU3s#g zgo!MbboHfb>Fk(b-)vI#6SZ^)!%w>im`EAa@nrd3!yVwi;fM278 z3obWO!tZY1*C<5+$U=O zSvl2d32;Fg7wL3LKwcmaQ9yOs<*@=s3GbY|uB#+^O7fYzZ#U*~C6k5J-@+0eWewnRxYz110k`y9etv=E+t3D9^zJDsX))^|6W6eZvKA)JEejNYl4RGtsD zuN93mxUcBQe%AeZ+Qae59z&sR!t+b2YO`k|JDFlqw6*yVl5Ywnel@z|&U~n(=x&&$ zsO|fOTFcz->3S@w?KxVo{*k+Ny&~l%1B~boyE#N{`cB)UnlyVpjcPo9JAqruG+(-( z-`u{eqBi3yPxF|OF@!=?&00L8lBN8~N)5gZC9jUtf~G@59Pj!{S#nwp)izF>-YcK| zz$YllWxIFLFhkKQ=$#rua&+UmW&O;TNAOYbzII?jCLTD=8E||ygp09$M7X-MxK9%M zKI)QG5M{Y>n{4q|j+k8Vi5s#82V(6vW6>UkaRyI_z?hu7LOfeQB+fZ*ZeOSw3~09nrD`e+{W{xfz6v zdoKu9a!cQjtSaIR^*z~=eE=?6R@1}J+Gge(IFCGUV%YA!I2>k6d6j<67<8Yzm+1@l{gFe#lb09-Y5(*}UB-eF1NL zRjfYGnyS?!kB2o$(aqredYu#W9hJvH5p8RW@u~!1{1EFB(x;E29&PuCvR*1UPE;|c zC^IOI=G!FX?u%^mLNUwMt}9mjVz9@Wow-Z>+Lbew@!WF8BhDf9U+v(kU0v91Icv0A z_p2gGc);9hVU}4TY%aEUB3*n3u47B+2spF}XX4FfzCvi08CWoCYGlc-iCDWFi%B0& zTUv@#O&p&rw%y6rBSS%0an`DRG*E1hB`cZg=~AMV=a+<=T}5(TE> zygk-xJn0q!#Z&}QSCq=vWoanB9(nwJDl29ym&+sJ`J;lfo4KP+A?EOSfk8o;aU-`T z+00w$5G}5>aJzrb+^{mfJ1Mi4PI`>yWb7OxQ0YMBpX@EoNR;C{*A5cPZ1t zt980E#x-S^Etw0>;oO)Cs0W>DBOd#iSTm|ANXqnSLSyI?>@Fak3&dJ6qE~JXo`Fo@ z#+BN5BJz0pDG7}cwy_*=(UiGOpA*%`ynEEMbr;3mF(=BoP*S|{bdRzj+NNhKYy-g( zuXo-PR&3v;9UoVP*4SDs6aF^iH_7EPIDxj&9F8iIao32;8LG7xr?%9*wq&;@tV{0#e%tC2As%ROGTs568AAf`NQ2CjdgJ`A(tpI@ zhK;GsYR4F`eArrUb0P}eNwI^o7 z8&YV;WjVe{@pCEFW$xpB|N4ZSX#?DaWUI1>Ou@NRj|~ybq_=Q_mgxkhcd^g0|7MsWqe}O zMdrh~*3i$}=Io=Q2Hiu0r#n;ahLG}orBO?XoRDPvMzCgLYc7~2oj*OL} zBBjz(MAYRb01SAshB-HBF!6~MLwvso`{m`{kl^9wdY5L~llQ5QGL)SuAUc>tR=Cc* zzmW-6$V_o*1RmDmEeNxz?c2z)KE3lmgJn8144m2&!5FeL!(MoP{S)_7+hv$8E_ zBJ6sfX&c#LnL4Z%A4f3|EU{4DWp)F#p(~d0@*6cjGw_Ss{NIXhqWH11=iYR~ZZ@yS z;W@vAX)g$z5cw0|KM(dDeEA~87T(Zt^Gw1$G_-#3{^yV{i$2QOCmzGOp9JTgiZCl? z3@rB8jJrXRxNBC7cXRDkXPL5nx9jQ{7A}_qwu)*YdW42G&Ufb`2Sw9{I!(k#wc&Sn zoD)GgIO}fx2?$9(B3p1MBr1nxkJWPYm6y{+&C+0D=Z zTH9y?+*zB19MR_O+}_gHc=fnZbH-dj8#sUr(VtirQ$Bc(9q# z1@US0${laZGFLo(ye)c?SoY@{Rqj%qWovSr_bD9Ti1m3v7eBl?{Fb~)u>8%gkfzJF zUR`1_^J|Lfo@Z<#y9d7phrK?L^t%Rso8$8d4POORj(JYbb3U=3dDZG^HX5xHUl4B6 z9Wx~A!uRTlKak>iKQ;m0121?F@SXzqYIch12F9$=Vb}%2lxP%`8R|L`4Z7ml?6McE z?1FdT>D*U<5Z8EKi0rN`7BW}1uJ=6ocO9hMbfyGs`(9>sENHSv30|wS?kTVf%D;KL zZhRz6KZcbxT~wivGRD+muR~3YwYSJTKA;o!s*V``lO~c$p?zqu1eob>SY=%tY(_l> zdM;#OP_zyT6Rh|lEV`&MrMk1O<;46!sck|V-b@)9s1V9>Ni?h08B#C7G_)LY*S2@? zR&B(mgiC7m+G=W>Q)lM8#cDTvp8VM~lg{xlQOK6fNG2Or$syUjDGkW?igDaKA! zpU7oZiKnc_Ygi`U|?vm?c+2ZLjw=QHqcipoR2RUlVveWn2F2t>~1r6|V{- z{7m4i8?ltzVp_(`n66zf(?bmj9sf5%pL>hGJPPW3If!vo9HQ^DTLaqj*mrlR$qX-q*n~ziK?Ku}u>tFw=Pbf2kGE|+(BcDgs z+Ee>3-lDYV(U+=~?X&^s#|P$I#an%9voNM|@eya0y^Ou-wY4@vvdEpAVAeYl0N4_|j36p`1Fb88REz!!@S=H24X zZl>jo=~O2UfT|hTK5~^}%-K+1*!|}p%7B`UHeQWxkBkr+54Pf5Zi#CGvi=KeY3Eqg zhf(G$c-y!u-zRmN$y@6mam(N>_D0s{bgpqhvt&>qhATitGz|kH7!%mj9=T<8TX2}| zC|jH9e)Q@V)F{7s!w}!MT)ULlS=lCv+s|KKFXn#OPH0CzOeP4tFk7UixyNE9%29zU zt|e9?OQT|VLagNWyS~7o`f7(-Ph~M;z3zh)dtJnM+&!HBgl?O;XU%g}<24hyqGYf9 z>c_?fHaC*j3v~AIN#~rKm07rJBNB>Pq<4O3v)k@vW@b3&NHpWrZ)#@0u^alLXti^T z26F5KSdHgCDvsVoy}iNJ-*kbK=mI!MyF1YkDkEhu$=J+O;2eYlq4Iu;`7e(l!U-&+ z1amKz%+bu#X2nQxNk_f5MIPg*mgFeZ99l18SZ|B@NRk09P~Y2q{dm z=B;(^TDYm@Z5w6aUl*G4I;j}w{3Gq)udE|YG4#)m@T5;1cFYJoFHX7 z%9AW{BvUAsFLo*h52fg?&YX$}Q~zNs2fCI+fa`K*#-UR}MmOC$L8J9~m{A^*kCN2+ zjHQ$s^Rr$jw6#6&XX9^|v#iy4CWMy;> z{jABzM3&(tEMEDdlMjDVy>Hnn+RNYR23>*6$4paUFXZe@=jk2nY$Wfa0?{IC`kpTX zw44d&Ar=)i&Z;rL_Nj4!Sa4`b1vpst%QO#xG~W>AJ$~8xf(|Dp$>@RWlth;ZyHlE^ zL{d>Iwp0>&7HF^sPbFzXsix=e$(7kU;#HJ4Ec!WqTgwfj0%Oi(#<(*Hi$QDDuB^@Bia60IO0& zyaJthyfer02fD_u{nr{2e?6JoHXEae@ChLX{$dhG)dW@lsy}>`=sm()@#siPJ*%$! zQ`n&JQ{o*uK~8d_?A4J*gF{60L4(G>i}KO5DwoE-gLXag zldfl6rJkhT91KwZK z_uGVCYl(DTZx?zqVNJHm_&;fyrv*^qiyi1B9$G`E6Fbdi?!@n0JI@pW%<~ z2|PGh^6p6iwB2275%!F8?Go>u=ZO>7={iuEty0bcg1s*9&=~wP3B#mr01tllKWKG* zo|LG|FyoWU2q}FPp-T?NbZ~mkUL zxaR(^>aP8f3BCU-^&B;wqoZ67TDoz{J-6c;66G)@%Ul*Av0PG{xkn_&t&Y<=%t%FH z?u@q4)5Mb8T1K0Z7P+lWZll=qnbYMt=lT8v-~GPrbA4Z4pV#aCb~*PTypz@va%VK6 z4C>z6CMYz^Od$X&;L`tf48#En*T0k2OrI+CtQAyw{J{hDmYkIDg*i%}Q8#|+^CcH# zj2HYE31?FtTK+bNlZ!Sg%(VPym-doRmeg%)Lu$f&?x{Rl=-otn?`GnNj2A0Pe5k z_!uJFEO5$~_e?4W%ho%_DrjIMBIdgfMhbXG097!B)xFBDOMI& z-Q(WThdJ8RHWxAR<-HC9aH~Vd26Sbh2SK))fHsCF)32(?p6Hmx`3GO6C;6a#X&4*u zws)&&o)J#tB03m#Vbm9V67RyH5tU(80D+F&T~?chX?C>b3*8z>)F`+eqfq>Od9kP3 zq3|{#G>J8{{Sg#2D&S!9lDTr}JOAzqc+Tn%0PNbH-rM@eSme4iCu;+3i>QbQ$MBr$<)@P9+D$H$C_slc|GKFWE`~8 z#aR0Z>$jjUcjhe0@vL)qj714CEGm z%F2Q$8C@EDGSE2gli-Q{#73Py>m>-th^I}qCGoBfRPV@2F87|2U394B8lz07h42*x zm01AFIdEZSS_9F5%I!9ep69*;*rT;o7M0rs9jJb*QlMk~cXuUzRICzN(B<>yX~mif0eb+YfCliuj!fv2x5tbnH(ohYf0rrwUFWvAb>s zdD)+>ZbQ_ptkkp@EVs6JX!myMeV9yIf&Qx$PN!Uc%A!YpL=J>gEi}!)z|e)dRvp)_ zgl62#%}3wQdp0FZtJggkLkP&&q*|)ff3RlqY(0u07p_qstsKqXx`2@TDgNY<`3$PX z)?BroWdemqW1?~QrmD#U`BHw6Oxd2VUMl|`YLBd%?5({wzsp2!+;yqBD%ntC=y#LD3 z9l!kWxJKWTmsXiXvhQ#YlyQh;B*hlD{Z4Sb#LI)og0pOX zu-y< z5Oc!!E)#+7D;|3+^X6}{k$5v{POH<$5fCOVO|!-6*QQ9swqJ7k%qlrl$gxV!u8z&U z?P0=#nE`ApaRo~TXfuqA*5TV{B~6Xi9`FNqiQ4(3d;|d_?C1N1@K*qbL{U zwIoC+M7A<3Z)t9;%QEcIE%jA@(lzCW9h{6XEpG8W`d|xQJ}a0BZ&Wtj$IbFeP;L9h z!B|UAfd}(Du6BvG9w&IxTP4eYC*InnR-1cYZ@<#-;^Qjb$f_EXiM~ytSgZ5F^r>tE zj)2rMIpAfx1M@~@)yTXIb{P2x>sQ|=zIfM+{p7&Cb9?IURK|Yr0U@tb)bjZqEqMC9 zQd2Q6Li;2`zcV{3L+&y1qaH-*6qUQXECfy=t#)SOsQ^^XckJG5+r;aM&MH32k5!je zYtcPe2}`Q~Yg2!jL#_@4w%g(}9lIh0Re-iFZs;_-^ft-V60dxb9q>EgRAa?8b@u{d z@LoUwPiaU=ILq?l+?q?B}#08FGoy^ecrkv}bMH z-&dKRbOvks&N{on z0C!x5)dj+5`veZf!}%$jQI;LdX^mk2GWyYVVzY1M+iQ4B3+-{#S+P(TIMaIJMmEA!*Y%YQMQUDbLxTg&Y4eQK8m+gyH|$Be)y*-smpWo9d;3ZM z;FNm##T=afiei6zki*;gG&{HlPorh>X;}0eL+dTqL@vD)N`uHj;8YXZSgZUm?nX`U zmYud84QLdG?lSzvapMJN9=<|3RXQqp6vg$U`Z8k`n{m8>Y{dAVeV?e@ef!Ed*p-*X zDh@B&zPnkAX2v-7>k_%F$>=Fx0DZ;v!*-)g>ok;%f}87i*PGqk)IKHag9aDtayff> zK4Ia59V~co9rgw1yFI5Lj=IdQZ@yYzEds>${8G_sCuoy{0KJfG%9Pr0<*cf?*aIl& za_92g=_PT4DI~hZG+v9Bk9;v*uaaqp!1548W&B*jp(BH*3G3E$+dyb5%3PCP;sC}*-Xr^N(7|6{dW!t>3YE{Zp|%s8FNAYxkP8L-YDw6VNBhGwbo z#-fEemw1mQY%C4pN)VLt!j_gfWdUr}CiIJN-x}7B-%cZGm1OQykg_gCs%680(0Gpm zddF50F-&pSV1#=X_!?zS{xkdP4N|7r0^c;If0~ZK4o)fbObxf~vEf#BcGD6uq0?39 z-`Y|A%c z+eUslA~zIG?n|ZLmH`GhDpzg?Uveg2n)fxMb&lKN)jaFufqOI!Gs<{0JxKoebYjLf z3lL+TYb7O`_|!s*iP>E;6rDM(o!mpZ{5#z}W;av$r0Q%p{x0oGj*#XWM0sPnvnl&j zJ*s2={hudy7KP_lE}&~d{DM=Q%|i*)8XD`F`*&rhH?Z3p%P}~B*m|+c>Fwp(_i(cO zcpC<{nbf_bhO8UuV@>7Hxu;8}zj*VFT&K#~?$NCv)o&JcEPPB-7ARG;@z4#-w)bVs z{q$eYD}T(sH2beqpkS?9q!AYnHFcxngcd>kcZdSXbMMxfgl?+#pNKVvGyxbiq07Kq z>hqHdU=tdNxpPHZJ^evR$!0H*!v6*eV)c9`f}N3Y+bQ?Jt9pL!MD%+bJN@Qud!)ts z2g`gwBZoV>E_i{(K6MYT{{Tolc?ER{(YdoCHYPH><_xu| z**)(!{4padxzHM}7t)QdAaPB<4}LiKv+=#JVaXrab~w%D@ZD9ccYUJjQR?<~Tv_)y z$5(&lP6n_fKHtQA8TLUr7W{8Y7Sd&U*G1&J`tf*>Ll#d86u<@g0hoMhBY{d&E>Ca z@^Ch91uVSmAmt4R^Zwlz@t&YuGqT%C!ENaRsI3oL^ehx!LZ>M5XC-Q#UkPgC zws%d$noiBeCBGLyEbpGO%3sao%jj!JNVhZ#YxCw^;$@}2|7OQWeZ)oelvG_IKW-*z z{~eLhJ6=Yu+MR@-7vL?J!cWZyp>8>zjT7VI0bTMm|A{CQKBSUR>vYQKWOL)2+#=JW zvP}}e@_eRt-ZoRu3)*m{cI34vcmup3K2|TbhyQ%})v0}qkB=}5i%sz*ThFaj+Ea-6-FA7Ugi z{$C3KssY|n+U_=S!{?*fV_ts4nU91-5oyBRNI;8;Z(LGpmpz@g64M3@2&EX%f5FIH z!BrVD5$m#m-r+UqR9pIQfdG$j$fPdGw%=%Y3Ny5}T!|ZR^BOeS0=jd-hLt_bGk6!D zYEo9ukk3h|D}ME&qkgkB1W`}oqa!-l_8aZEdbK@x*f6+3iv}4JWJV{1s^gKIFznH= zKN8TT&x7>=HO?F<%3u_?-;I03{Q&w1M%2TX&Vc!~0|84Ha6|{uqTVf^#+Lc$M;<_X z1$u*dnpDS4L;CQzPrV7SPph!|osx%AznKheP;v+w_;@E~sIwztwQCNUHk^ks0)KI+ z#4VP)!}4zEhKe|@O{kmL5<3y0(F`C$2xWF_2Mb?!FxI%#I_cw?R_4d3fiW}ji;0@& zUqM0ngmY71wB1L=#BqCyBKW=kXCL=>w%W_0b;Z{@4Kde`hlodi)Yj>6g|&C$e*kWM Bg>C=< literal 0 HcmV?d00001 diff --git a/verification/README.md b/verification/README.md index c3aa344..6a0de92 100644 --- a/verification/README.md +++ b/verification/README.md @@ -2,15 +2,15 @@ This Chapter explains how to use the verification functionality of ILAng to generate verification target to work with existing -model checkers. Currently we support Cadence JasperGold, CoSA, CoSA2. -For other Verilog model checker, we can generate a standalone -Verilog with embedded assumptions and assertions using the -SVA format. +model checkers. Currently we support Cadence JasperGold, CoSA, +Pono (previously named CoSA2). For other Verilog model checker, +we can generate a standalone Verilog with embedded assumptions +and assertions using the SVA format. -For verification, you will need (1) a ILA model (2) the Verilog +For verification, you will need (1) an ILA model (2) the Verilog module (3) the refinement relation to map ILA and Verilog, -this is shown in the following figure. +this is shown in the following figure. ![](.gitbook/assets/rtl-verify-arch.png) From ff68f9c1681952e898e5b864b40edebffc248f8b Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 2 Nov 2020 11:06:41 -0500 Subject: [PATCH 17/26] merge code style --- verification/README.md | 13 ++----- verification/example.md | 76 ++++++++++++++------------------------ verification/refinement.md | 3 +- 3 files changed, 32 insertions(+), 60 deletions(-) diff --git a/verification/README.md b/verification/README.md index 6a0de92..a27ad97 100644 --- a/verification/README.md +++ b/verification/README.md @@ -1,16 +1,9 @@ # Verification -This Chapter explains how to use the verification functionality -of ILAng to generate verification target to work with existing -model checkers. Currently we support Cadence JasperGold, CoSA, -Pono (previously named CoSA2). For other Verilog model checker, -we can generate a standalone Verilog with embedded assumptions -and assertions using the SVA format. +This Chapter explains how to use the verification functionality of ILAng to generate verification target to work with existing model checkers. Currently we support Cadence JasperGold, CoSA, Pono (previously named CoSA2). For other Verilog model checker, we can generate a standalone Verilog with embedded assumptions and assertions using the SVA format. +For verification, you will need \(1\) an ILA model \(2\) the Verilog module \(3\) the refinement relation to map ILA and Verilog, this is shown in the following figure. -For verification, you will need (1) an ILA model (2) the Verilog -module (3) the refinement relation to map ILA and Verilog, -this is shown in the following figure. +![](../.gitbook/assets/rtl-verify-arch.png) -![](.gitbook/assets/rtl-verify-arch.png) diff --git a/verification/example.md b/verification/example.md index 2d957b7..c259b94 100644 --- a/verification/example.md +++ b/verification/example.md @@ -1,26 +1,18 @@ -# Examples of Refinement Relation +# Examples -Here we'd like to give some examples of the refinement relations. -The features described may include some of the syntactic sugar we are currently working on, -which will be marked in the text. +Here we'd like to give some examples of the refinement relations. The features described may include some of the syntactic sugar we are currently working on, which will be marked in the text. ## Conditional Mapping -In variable mapping section, the conditional mapping is helpful in many cases. Below we give some -examples using conditional mapping. +In variable mapping section, the conditional mapping is helpful in many cases. Below we give some examples using conditional mapping. ### Mapping Loop Body with Unrolled Pipelines -Suppose we have a specification for AES-128 function, which consist of 10 rounds of cryptographic operations, each round takes results from previous round and generate new ciphertext and new round key which will be used in the next round. -In the ILA model, this is described with the help of child-instructions that form a loop. -Whereas, the implementation is a pipeline which corresponds to an unrolling of the loop in the specification. -This is illustrated in the figure below. +Suppose we have a specification for AES-128 function, which consist of 10 rounds of cryptographic operations, each round takes results from previous round and generate new ciphertext and new round key which will be used in the next round. In the ILA model, this is described with the help of child-instructions that form a loop. Whereas, the implementation is a pipeline which corresponds to an unrolling of the loop in the specification. This is illustrated in the figure below. -![](.gitbook/assets/aes-128-loop.png) - -When verifying the child-instructions, we need to map the state variables holding intermediate results \(suppose it is named as `ciphertext` in ILA\) with signals in Verilog. -However, because the loop is unrolled into a 10-stage pipeline, the corresponding Verilog signal for `ciphertext` is dependent on the round. Therefore, we need conditional mapping here, which can be specified as follows. +![](../.gitbook/assets/aes-128-loop.png) +When verifying the child-instructions, we need to map the state variables holding intermediate results \(suppose it is named as `ciphertext` in ILA\) with signals in Verilog. However, because the loop is unrolled into a 10-stage pipeline, the corresponding Verilog signal for `ciphertext` is dependent on the round. Therefore, we need conditional mapping here, which can be specified as follows. ```javascript "state mapping": { @@ -44,7 +36,7 @@ Or, alternatively, you can use: } ``` -Regarding the `round` variable in ILA, because the loop in Verilog is fully unrolled and the effects of `round` are already reflected in the mapping of `ciphertext`, we don't need a mapping for `round`. We can simply write: +Regarding the `round` variable in ILA, because the loop in Verilog is fully unrolled and the effects of `round` are already reflected in the mapping of `ciphertext`, we don't need a mapping for `round`. We can simply write: ```javascript "state mapping": { @@ -53,27 +45,21 @@ Regarding the `round` variable in ILA, because the loop in Verilog is fully unr } ``` - -{% hint style="tip" %} +{% hint style="info" %} The condition are treated as a ordered list, namely, only when the first condition does not hold, will the rest of the mapping be considered. You can have a default case with condition `1'b1` or `null`. {% endhint %} - ### Mapping State Variables with On-the-Fly Values -When tackling pipelined designs, for a software-visible state variable (e.g., an architectural register) it is also common that there might be multiple places to look for, especially the value on-the-fly inside the pipeline. -Because of forwarding logic, a newly computed value, though not yet written back to the register file, can still be observable for an instruction -following it. In the refinement relation, we provide two possible ways to handle the case: conditional mapping and light-weight flushing. - +When tackling pipelined designs, for a software-visible state variable \(e.g., an architectural register\) it is also common that there might be multiple places to look for, especially the value on-the-fly inside the pipeline. Because of forwarding logic, a newly computed value, though not yet written back to the register file, can still be observable for an instruction following it. In the refinement relation, we provide two possible ways to handle the case: conditional mapping and light-weight flushing. -![](.gitbook/assets/simplepipe.png) +![](../.gitbook/assets/simplepipe.png) - -**Conditional mapping.** Usually, inside the pipeline, there are book-keeping logic to track the location of the latest update to an architectural register (e.g., the scoreboard). Therefore, one can use this logic to map an architectural register to the corresponding microarchitectural register in the pipeline. Above shows an examples of such a pipeline, it has three stages (not counting the stages before instruction dispatch) and a per-register record `reg_X_w_stage`. The left-most bit indicates if the EX (execute) stage has a valid write to register X. The right-most bit indicates if the second stage has a write. Based on status indicated by this scoreboard, one can write the refinement for the register as below. It first checks the left-most bit of the scoreboard entry and then the right-most bit and finally the default case. Note how the priority list is used for condition. +**Conditional mapping.** Usually, inside the pipeline, there are book-keeping logic to track the location of the latest update to an architectural register \(e.g., the scoreboard\). Therefore, one can use this logic to map an architectural register to the corresponding microarchitectural register in the pipeline. Above shows an examples of such a pipeline, it has three stages \(not counting the stages before instruction dispatch\) and a per-register record `reg_X_w_stage`. The left-most bit indicates if the EX \(execute\) stage has a valid write to register X. The right-most bit indicates if the second stage has a write. Based on status indicated by this scoreboard, one can write the refinement for the register as below. It first checks the left-most bit of the scoreboard entry and then the right-most bit and finally the default case. Note how the priority list is used for condition. ```javascript "state mapping": { - ..., + ..., "r1" : [ {"cond":"m1.reg_1_w_stage[1]", "map":"ex_alu_result"}, {"cond":"m1.reg_1_w_stage[0]", "map":"ex_wb_val"}, {"cond":null, "map":"register[1]"} ], @@ -82,25 +68,25 @@ following it. In the refinement relation, we provide two possible ways to handle } ``` -**Light-weight flushing.** This is a setting similar to what has been used in ARM's ISA-Formal work. One can use prophecy variables (variables holding values available in the future) to help construct the mapping. The value-on-the-fly will be written back to the architectural register file in the future and we can map a register with that future value. Our variable mapping allows this mapping using what we call "value holder" (it is essentially an auxiliary variable and note that it can also hold history values). The light-weight flushing setting is illustrated in the figure below: +**Light-weight flushing.** This is a setting similar to what has been used in ARM's ISA-Formal work. One can use prophecy variables \(variables holding values available in the future\) to help construct the mapping. The value-on-the-fly will be written back to the architectural register file in the future and we can map a register with that future value. Our variable mapping allows this mapping using what we call "value holder" \(it is essentially an auxiliary variable and note that it can also hold history values\). The light-weight flushing setting is illustrated in the figure below: -![](.gitbook/assets/future-values.png) +![](../.gitbook/assets/future-values.png) Again for the previous pipeline example, we can have the variable mapping as follows: ```javascript "state mapping": { - ..., + ..., "r1" : [ {"cond":"__START__", "map":"#valueholder_r1#"}, - {"cond":"__IEND__", "map":"register[1]"}], + {"cond":"__IEND__", "map":"register[1]"}], "r2" : [...], ... } ``` -Here `#` quoted names are the names to value holders. The condition `__START__` indicates, at the beginning of the instruction under verification, `r1` is mapped to the value holder (a future value in our case) and at the end of the instruction execution (indicated by `__IEND__`), it is mapped to the write-back value in the register file. +Here `#` quoted names are the names to value holders. The condition `__START__` indicates, at the beginning of the instruction under verification, `r1` is mapped to the value holder \(a future value in our case\) and at the end of the instruction execution \(indicated by `__IEND__`\), it is mapped to the write-back value in the register file. -Value holders are defined in the `value-holder` section in the variable mapping file. Below is an example. The condition here indicates when to take the value of `m1.register[1]` and hold it for use universally. `stage_tracker` is an example of the monitor that one may add to track the stage of an instrcution in the pipeline (if the original design already has some tracking mechanism, it can be used instead). +Value holders are defined in the `value-holder` section in the variable mapping file. Below is an example. The condition here indicates when to take the value of `m1.register[1]` and hold it for use universally. `stage_tracker` is an example of the monitor that one may add to track the stage of an instrcution in the pipeline \(if the original design already has some tracking mechanism, it can be used instead\). ```javascript "value-holder": { @@ -110,35 +96,30 @@ Value holders are defined in the `value-holder` section in the variable mapping "width": 8 } } - ``` -{% hint style="tip" %} +{% hint style="info" %} `width` in the above example can be set to `"auto"` which will allow the tool to automatically determine the width of the value holder. {% endhint %} - -{% hint style="working" %} +{% hint style="info" %} We are working on a syntactic sugar in the form of `val@cond` in the `state-mapping` part which can automatically generate a value holder. In the future we shall allow the following shortcut: ```javascript "state mapping": { - ..., + ..., "r1" : [ {"cond":"__START__", "map":"register[1] @ (stage_tracker == 1)"}, - {"cond":"__IEND__", "map":"register[1]"}], + {"cond":"__IEND__", "map":"register[1]"}], "r2" : [...], ... } ``` - {% endhint %} - ## Stage Tracker As shown by the previous example, it is very often that one would like to track the stage of an instruction. Currently this is done via inline Verilog monitors. For the previous example, we have a monitor like the following. - ```javascript "verilog-inline-monitors" : { "stage_tracker" : { @@ -154,7 +135,7 @@ As shown by the previous example, it is very often that one would like to track This monitor starts the tracking when the instruction under verification starts to execute and counts up till the instruction finishes. This works for the simple case as the pipeline will not stall and the tracker does not need to stall either. However, in general this is not true and below we provide an example to handle a more general case. -In the example below, there are 3 intermediate stages and a final write-back (s4) stage. The monitor here uses the signals inside the pipeline like `m1.s1_to_s2$D_IN` and `m1.s1_to_s2$EN` to tell if the current instruction moves to the next stage. These are indicated by the signals like `s1_to_s2`. +In the example below, there are 3 intermediate stages and a final write-back \(s4\) stage. The monitor here uses the signals inside the pipeline like `m1.s1_to_s2$D_IN` and `m1.s1_to_s2$EN` to tell if the current instruction moves to the next stage. These are indicated by the signals like `s1_to_s2`. ```javascript "verilog-inline-monitors" : { @@ -243,14 +224,10 @@ In the example below, there are 3 intermediate stages and a final write-back (s4 } ``` - - -{% hint style="working" %} -As the tracking of pipeline stages is a very common scenario, we are also working on a template to automatically generate a pipeline stage tracker. We expect this to handle the case of branching pipelines (where there are fan-out points to dispatch instructions through any of the downstream pipelines, and merge point that coalesce the end of multiple pipelines). Events are specified based on their effects on the stages as -`exit` event and `enter` event. We shall also allow caching temporary values in auxiliary variables at the time of the events. +{% hint style="info" %} +As the tracking of pipeline stages is a very common scenario, we are also working on a template to automatically generate a pipeline stage tracker. We expect this to handle the case of branching pipelines \(where there are fan-out points to dispatch instructions through any of the downstream pipelines, and merge point that coalesce the end of multiple pipelines\). Events are specified based on their effects on the stages as `exit` event and `enter` event. We shall also allow caching temporary values in auxiliary variables at the time of the events. {% endhint %} - ## Simple Delays Another common scenario is that we'd like to delay a signal for a few cycles. The general way for this is an inline-monitor. For example, we'd like to delay `xram_ack` for one cycle and use it as the finish condition for an instruction. First, we can have a few lines in `verilog-inline-monitors` section as follows: @@ -269,7 +246,8 @@ Another common scenario is that we'd like to delay a signal for a few cycles. Th Recall that `defs` contains the auxiliary variables that we'd like to create and `refs` are the signals in the original design that we use in the monitor. -{% hint style="working" %} +{% hint style="info" %} We are working on a syntactic sugar in the form of `signal ## cycle` and `(expression) ## cycle` that will create verilog-inline-monitor automatically to delay a signal for the given number of cycles. {% endhint %} + diff --git a/verification/refinement.md b/verification/refinement.md index 0ef1cf2..0f6a15d 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -181,7 +181,7 @@ Memory state variable might be internal or external to the module. An internal m } ``` -The above annotation specifies memory named as `rf` and `mem` as internal and external respectively. Being internal or external affects how properties are generated. The mapping of internal memory is element-wise with expressions comparing two verilog arrays entry by entry, which is inefficient for a large memory. The mapping of external memory will use memory abstraction, which is more efficient. (In the future, we will support mapping internal memory using the Array data-type of the underlying property verifier.) +The above annotation specifies memory named as `rf` and `mem` as internal and external respectively. Being internal or external affects how properties are generated. The mapping of internal memory is element-wise with expressions comparing two verilog arrays entry by entry, which is inefficient for a large memory. The mapping of external memory will use memory abstraction, which is more efficient. \(In the future, we will support mapping internal memory using the Array data-type of the underlying property verifier.\) ## Uninterpreted Function Mapping @@ -290,3 +290,4 @@ This creates a 2-bit variable `stage_tracker` to track the number of cycles \(th Value holders and monitors are normally only in effect when verifying instructions. If you want a monitor to appear also when verifying the invariants, you can add the `"keep-for-invariants":true` attribute in the monitor's description following the `defs` and `refs` attributes. + From 09e8a0e8b2748d3dfe553dd779c4c60df27c2fad Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 2 Nov 2020 11:07:56 -0500 Subject: [PATCH 18/26] rm empty line --- verification/example.md | 1 - verification/refinement.md | 1 - 2 files changed, 2 deletions(-) diff --git a/verification/example.md b/verification/example.md index c259b94..a952d73 100644 --- a/verification/example.md +++ b/verification/example.md @@ -250,4 +250,3 @@ Recall that `defs` contains the auxiliary variables that we'd like to create and We are working on a syntactic sugar in the form of `signal ## cycle` and `(expression) ## cycle` that will create verilog-inline-monitor automatically to delay a signal for the given number of cycles. {% endhint %} - diff --git a/verification/refinement.md b/verification/refinement.md index 0f6a15d..c6b4117 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -290,4 +290,3 @@ This creates a 2-bit variable `stage_tracker` to track the number of cycles \(th Value holders and monitors are normally only in effect when verifying instructions. If you want a monitor to appear also when verifying the invariants, you can add the `"keep-for-invariants":true` attribute in the monitor's description following the `defs` and `refs` attributes. - From 4cd22c6c4d0cd5b24351c24500b5e9347d4d510a Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 23 Nov 2020 20:20:12 -0500 Subject: [PATCH 19/26] memory-ports --- verification/refinement.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/verification/refinement.md b/verification/refinement.md index c6b4117..cdd013d 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -156,7 +156,7 @@ The Verilog module comes with a set of I/O signals and the tool needs to know ho * `**SO**` directive, indicating that this is actually a direct output from a visible state variable \(a state variable that is modeled in the ILA\). * `**RESET**` or `**NRESET**` directive. Indicating that this signal is the reset signal, active-high or active-low \(we assume synchronous reset\). * `**CLOCK**` directive, indicating that this is the clock signal. -* `**MEM**name.signal` directive, indicating this signal is the connection to an external/shared memory. The name part should be the ILA state variable name of the memory, and the signal part could be one of the following: `wdata`,`rdata`, `waddr`,`raddr`, `wen`, `ren`. If the signal does not directly correspond to the write/read data, write/read address, write/read enable signal, it should be specified as `**KEEP**`, you can specify the mapping using the additional assumptions. +* `**MEM**name.signal` directive, indicating this signal is the connection to an external/shared memory. The name part should be the ILA state variable name of the memory, and the signal part could be one of the following: `wdata`,`rdata`, `waddr`,`raddr`, `wen`, `ren`. If the signal does not directly correspond to the write/read data, write/read address, write/read enable signal, it should be specified as `**KEEP**`, you can specify the mapping using "annotation" which will be dicussed below. For example, for a Verilog input signal `control`, the effects of applying different directives are: @@ -183,6 +183,21 @@ Memory state variable might be internal or external to the module. An internal m The above annotation specifies memory named as `rf` and `mem` as internal and external respectively. Being internal or external affects how properties are generated. The mapping of internal memory is element-wise with expressions comparing two verilog arrays entry by entry, which is inefficient for a large memory. The mapping of external memory will use memory abstraction, which is more efficient. \(In the future, we will support mapping internal memory using the Array data-type of the underlying property verifier.\) +For the external memory, it is likely that there isn't a one-to-one mapping between the module interface and the six signals required by the memory abstraction module: `wdata` (write-data) ,`rdata` (read-data), `waddr` (write-address),`raddr` (read-address), `wen` (write-enable), `ren` (read-enable). Therefore, we support specifying the mapping using the annotation here. An example of the syntax is given below. + +```javascript + "annotation" : { + "memory-ports" : { + "MemoryName.port1" : "Verilog-expression-here", + "MemoryName.port2" : "Verilog-expression-here" + } + } +``` + +In the above example, `MemoryName` should be the name of the memory state variable in ILA and `port1`, `port2` should be one of `wdata` (write-data) ,`rdata` (read-data), `waddr` (write-address),`raddr` (read-address), `wen` (write-enable), `ren` (read-enable). The Verilog expression after the colon represents how to use the Verilog signal to compute the interface signals. +Note that this kind of mapping assumes the ports of an abstract memory state can be represented as a function of solely the Verilog signals. If this is not feasible for the design you are looking at, you can use the additional mapping capability provided by `mapping control` section described later in this chapter. + + ## Uninterpreted Function Mapping The ILA model may use uninterpreted functions, however, in the verification, the tool must know the correspondence of this uninterpreted function in order to reason about the correctness. In the `functions` field of the _var-map_ JSON, a map should be provided if uninterpreted function is used in the ILA model. The keys of the map are the function names, with the values in a list. Each element of this list is for one application of this function. Per each function application, the tool needs to know the correspondence of the arguments/result in the Verilog and when that happens, this is like a condition/mapping pair, and it is specified as a list. The correspondence of the function result goes first followed by the arguments \(in the same order as the arguments in ILA function definitions\). From 33c7e9433df442e6c63bfa12898cac4836719712 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 23 Nov 2020 21:36:28 -0500 Subject: [PATCH 20/26] more examples for memory mapping --- verification/example.md | 196 +++++++++++++++++++++++++++++++++++++ verification/refinement.md | 22 +++++ 2 files changed, 218 insertions(+) diff --git a/verification/example.md b/verification/example.md index a952d73..408b3fd 100644 --- a/verification/example.md +++ b/verification/example.md @@ -250,3 +250,199 @@ Recall that `defs` contains the auxiliary variables that we'd like to create and We are working on a syntactic sugar in the form of `signal ## cycle` and `(expression) ## cycle` that will create verilog-inline-monitor automatically to delay a signal for the given number of cycles. {% endhint %} +## Mapping of Memory + +The specification of memory state variable mapping can be very different depends on the types of memory. +The memory in Verilog be internal or external. While the memory in ILA may be modeled as an internal or memory state variable, as well. +There isn't a strict dependency between the two choices. And there are four combinations as described below. + +### Internal Memory in both ILA and RTL + +Currently, there isn't a uniform and scalable way to handle this case for both Pono and JasperGold. +The current implemented approach is to declare the memory as internal in the annotation section, however, this won't scale to large memory. +Below gives an example. + +The implementation contains two internal memories `mema` and `memb`, when `start` signal is asserted, it will swap the contents between two addresses in these two memories, where the addresses are specified by the input indices. + +```text +// swap with internal memory (im) +module swap ( + input clk, // Clock + input rst, // Synchronous reset active high + input [3:0] addra, + input [3:0] addrb, + input start); + +reg [7:0] mema[0:15]; +reg [7:0] memb[0:15]; + + +always @(posedge clk) begin + if (start) begin + mema[addra] <= memb[addrb]; + memb[addrb] <= mema[addra]; + end +end +endmodule +``` + +The ILA model also model these as internal memory state variables and the ILA has only one instruction `SWAP`. + +```cpp + auto memswap = Ila("MemorySwap"); + memswap.SetValid(BoolConst(true)); + + auto addra = memswap.NewBvInput("addra", 4); + auto addrb = memswap.NewBvInput("addrb", 4); + auto start = memswap.NewBvInput("start", 1); + + auto mema = memswap.NewMemState("mema", 4, 8); + auto memb = memswap.NewMemState("memb", 4, 8); + + { + auto SWAP = memswap.NewInstr("SWAP"); + SWAP.SetDecode(start == 1); + + auto dataa = Load(mema, addra); + auto datab = Load(memb, addrb); + + SWAP.SetUpdate(mema, Store(mema, addra, datab)); //mema[addra] = memb[addrb] + SWAP.SetUpdate(memb, Store(memb, addrb, dataa)); //memb[addrb] = mema[addra] + } +``` + +The mapping of the memories in ILA and Verilog is very straightforward (below only shows the `state mapping` section). + +```javascript + "state mapping": { + "mema":"mema", + "memb":"memb"}, +``` + +This simple handling will work for all backends, but would not scale to large memories. +If it is possible to convert the internal memory to an external one by commenting away the declaration of the Verilog array and the associated read/write logic, then we can use the memory abstraction approach that applies to external memory. (Note in the conversion, please keep the read/write signals intact as they will be treated as if they are interface signals to the external memory, and our tool can automatically pull these signals to the top level module.) + + +{% hint style="info" %} +Currently, there is a limitation on the memory abstraction model, which only supports making one read and one write concrete. So, if the internal array is read or written more than twice during the execution of the instruction and they must be concrete to avoid the spurious counterexample due to the abstraction, you might have to consider the commercial solution (the Proof Accelerator in JasperGold, which is essentially a memory abstraction but can be configured to support multiple concrete read and write). +{% endhint %} + +{% hint style="info" %} +Specifically, for the Pono backend, we are working on a solution to use SMT array theory to support mapping of arrays. However, although no Verilog modification is needed, it might be difficult for the model checkers to prove unbounded correctness. +{% endhint %} + +{% hint style="info" %} +We are also considering the possibility of intergrating CHC solvers to overcome the above difficulty when handling arrays. Comments and feedbacks on this are greatly appreciated. +{% endhint %} + +### Internal Memory in ILA and External Memory in RTL + +Now suppose we want to convert the above Verilog to external memories, we need to comment away the declaration of Verilog arrays as well as the associated read/write logic. + +```text +// swap with internal memory (im) (now converted to external memory) +module swap ( + input clk, // Clock + input rst, // Synchronous reset active high + input [3:0] addra, + input [3:0] addrb, + input start); + +// reg [7:0] mema[0:15]; +// reg [7:0] memb[0:15]; + + +// always @(posedge clk) begin +// if (start) begin +// mema[addra] <= memb[addrb]; +// memb[addrb] <= mema[addra]; +// end +// end + +endmodule +``` + +Below shows the signal mapping below. Here it is a bit tricky as in Verilog there is no such signal that holds the output of the +read from these two arrays (they are directly used to overwrite the contect in another location). So we will need to create auxiliary variables to support this. In the table, we use `#mema_rdata#` and `#memb_rdata#` as the place-holders. + +| memory.port | signal | +|------------- |-------------- | +| mema.ren | start | +| mema.raddr | addra | +| mema.rdata | #mema_rdata# | +| mema.wen | start | +| mema.waddr | addra | +| mema.wdata | #memb_rdata# | +| memb.ren | start | +| memb.raddr | addrb | +| memb.rdata | #memb_rdata# | +| memb.wen | start | +| memb.waddr | addrb | +| memb.wdata | #mema_rdata# | + + +The overall state variable mapping should looks like this: + +```json +{ + "models": { "ILA":"m0" , "VERILOG": "m1" }, + "instruction mapping": [], + "state mapping": { + "mema":"**MEM**mema", + "memb":"**MEM**memb"}, + + "interface mapping": { + "rst":"**RESET**", + "clk":"**CLOCK**", + "addra":"addra", + "addrb":"addrb", + "start":"start" + }, + + "annotation" : { + "memory-ports" : { + "mema.ren" : "start" , + "mema.raddr" : "addra" , + "mema.rdata" : "#mema_rdata#" , + "mema.wen" : "start" , + "mema.waddr" : "addra" , + "mema.wdata" : "#memb_rdata#" , + "memb.ren" : "start" , + "memb.raddr" : "addrb" , + "memb.rdata" : "#memb_rdata#" , + "memb.wen" : "start" , + "memb.waddr" : "addrb" , + "memb.wdata" : "#mema_rdata#" + } + }, + + "verilog-inline-monitors" : { + "read_value_holder" : { + "verilog": [], + "defs" :[ ["mema_rdata", 8, "wire"],["memb_rdata", 8, "wire"] ], + "refs" :[] + } + } +} +``` + +And to aid efficient reasoning, you should also enable `MemAbsReadAbstraction` option in the configuration for `VerilogVerificationTargetGenerator`. An example is given below: + +```cpp + VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; // default configuration + vtg_cfg.MemAbsReadAbstraction = true; // enable read abstraction in the abstract memory model + VerilogVerificationTargetGenerator vg( ... /* the arguments are omitted here */ , + vtg_cfg); // give vtg_cfg as the extra configuration +``` + +### External Memory in ILA and Internal Memory in RTL + +In this case, you may want to consider to convert the internal Verilog memory as external using the approach described above. This will help with mapping and also the automated reasoning in the underlying model checkers. + +### External Memory in both ILA and RTL + +In this case, you can try to map the directly interface signals between ILA and RTL, if +you are unable to write it as an one-to-one mapping in `interface mapping` section, `mapping control` section is available for you. + + + diff --git a/verification/refinement.md b/verification/refinement.md index cdd013d..690eeeb 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -73,6 +73,7 @@ The variable mapping in the JSON file is a map data structure. The keys of this 2. A predicate that has at least a `=` in it \(you can use `>=` , `<=` , `==` and etc.\) This is just for our parser to distinguish it from the first case. 3. A string-string pair that is in the form of a list or map. If it is given as a list, the first element is regarded as the condition and the second element is regarded as the mapping. It conveys the meaning of "when the condition is true, the ILA and Verilog variables should have the mapping". If the condition is not true, there is no mapping guaranteed. If the string-string pair is given as a map, it must have two elements. One element should have the key `cond` and the other should have the key `map`. The `map` part could be a string of Verilog variable name as in case \(1\) or a Verilog expression as case \(2\). 4. A list of string-string pairs, each pair follows requirement in \(3\). +5. If the ILA variable on the left is a memory, the right side depends on whether the Verilog memory is internal or external. If inside Verilog, there is an array that corresponds to this memory, you can directly use this name on the right side. Otherwise, you can make this ILA memory to map with an external memory using `"ILA-mem-name":"**MEM**ILA-mem-name"`. Below are some of the examples: @@ -84,6 +85,8 @@ Below are some of the examples: "ILA_state_3" : ["__START__", "Verilog_state_3"], // case 3.a "ILA_state_4" : { "cond":"__START__", "map":"Verilog_state_4"}, // case 3.b "ILA_state_5" : [["__START__", "Verilog_state_5"], ["__IEND__","Verilog_state_6"]], // case 4 + "ILA_mem_state" : "Verilog_array_name", // case 5.a : internal memory in Verilog + "ILA_mem_state" : "**MEM**ILA_mem_state", // case 5.b : external memory in Verilog // more ... }, // other fields ... @@ -107,6 +110,13 @@ wire variable_map_assume___p7__ILA_state_4 = (~ __START__) || (__m16__) ; wire __m18__ = ( (~ __START__ ) || ( Verilog_state_5 == ILA_state_5 ) ) && ( ~( ~__START__ && __IEND__ ) || Verilog_state_6 == ILA_state_5 ) ; // __START__ --> match1 && (~__START__ && __IEND__) --> match2 wire variable_map_assume___p9__ILA_state_5 = (~ __START__) || (__m18__) ; + +// map to an internal Verilog array : element-wise equality +assign __m20__ = ( __ILA_SO_mem_0 == VerilogArray_0_)&&( __ILA_SO_mem_1 == VerilogArray_1_)&&... ; +assign variable_map_assume___p11__ = (~ __START__ )|| (__m20__) ; + +// map to an external Verilog array : using memory abstraction +// no assumption is needed ``` and the assertions: @@ -126,6 +136,18 @@ wire variable_map_assert___p7__ILA_state_4 = (~ __IEND__) || (__m6__) ; wire __m8__ = ( (~ __START__ ) || ( Verilog_state_5 == ILA_state_5 ) ) && ( ~( ~__START__ && __IEND__ ) || Verilog_state_6 == ILA_state_5 ) ; // __START__ --> match1 && (~__START__ && __IEND__) --> match2 wire variable_map_assert___p9__ILA_state_5 = (~ __IEND__) || (__m8__) ; + +// map to an internal Verilog array : element-wise equality +assign __m10__ = ( __ILA_SO_mem_0 == VerilogArray_0_)&&( __ILA_SO_mem_1 == VerilogArray_1_)&&... ; +assign variable_map_assert___p11__ = (~ __IEND__ )|| (__m10__) ; + +// map to an external Verilog array : using memory abstraction +absmem #( + .AW(32), + .DW(8), + .TTS(4294967296) ) +mi0(..., .mem_EQ_(mem_EQ_) ); +assign variable_map_assert__p13__ = (~ __IEND__) || (mem_EQ_) ; ``` One note in the above example: the condition can refer to special signals \(`__START__` and `__IEND__`\), which are the condition when the instruction-under-verification starts to execute and finishes. From eb15bffa1e0b3c8df30f451d9a4226e09f32b793 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 23 Nov 2020 21:37:09 -0500 Subject: [PATCH 21/26] correct typo --- verification/example.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verification/example.md b/verification/example.md index 408b3fd..f61eb85 100644 --- a/verification/example.md +++ b/verification/example.md @@ -311,7 +311,7 @@ The ILA model also model these as internal memory state variables and the ILA ha } ``` -The mapping of the memories in ILA and Verilog is very straightforward (below only shows the `state mapping` section). +The mapping of the memories in ILA and Verilog is very straight-forward (below only shows the `state mapping` section). ```javascript "state mapping": { From ca8afbd31ebe144a72603ebf223d4896ef2cf3b5 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 1 Feb 2021 17:13:13 -0500 Subject: [PATCH 22/26] update rfmap spec and example --- verification/example.md | 314 ++++---------------- verification/refinement.md | 581 +++++++++++++++++++++++++------------ 2 files changed, 454 insertions(+), 441 deletions(-) diff --git a/verification/example.md b/verification/example.md index f61eb85..536efbb 100644 --- a/verification/example.md +++ b/verification/example.md @@ -1,6 +1,6 @@ # Examples -Here we'd like to give some examples of the refinement relations. The features described may include some of the syntactic sugar we are currently working on, which will be marked in the text. +Here we'd like to give some examples of the refinement mapping. ## Conditional Mapping @@ -8,7 +8,7 @@ In variable mapping section, the conditional mapping is helpful in many cases. B ### Mapping Loop Body with Unrolled Pipelines -Suppose we have a specification for AES-128 function, which consist of 10 rounds of cryptographic operations, each round takes results from previous round and generate new ciphertext and new round key which will be used in the next round. In the ILA model, this is described with the help of child-instructions that form a loop. Whereas, the implementation is a pipeline which corresponds to an unrolling of the loop in the specification. This is illustrated in the figure below. +Suppose we have a specification for AES-128 function, which consist of 10 rounds of cryptographic operations, each round takes results from previous round and generate new ciphertext and new round key which will be used in the next round. In the ILA model, this is described with the help of child-instructions that form a loop. The implementation is a pipeline which corresponds to an unrolling of the loop. This is illustrated in the figure below. ![](../.gitbook/assets/aes-128-loop.png) @@ -24,17 +24,6 @@ When verifying the child-instructions, we need to map the state variables holdin } ``` -Or, alternatively, you can use: - -```javascript - "state mapping": { - "ciphertext" : [{"cond":"ILA.round == 0", "map":"s_in" }, - {"cond":"ILA.round == 1", "map":"s0" }, - {"cond":"ILA.round == 2", "map":"s1" }, - ... - ] - } -``` Regarding the `round` variable in ILA, because the loop in Verilog is fully unrolled and the effects of `round` are already reflected in the mapping of `ciphertext`, we don't need a mapping for `round`. We can simply write: @@ -46,7 +35,7 @@ Regarding the `round` variable in ILA, because the loop in Verilog is fully unro ``` {% hint style="info" %} -The condition are treated as a ordered list, namely, only when the first condition does not hold, will the rest of the mapping be considered. You can have a default case with condition `1'b1` or `null`. +The condition are treated as a ordered list, namely, only when the first condition does not hold, will the rest of the mapping be considered. You can have a default case with condition `1'b1`. {% endhint %} ### Mapping State Variables with On-the-Fly Values @@ -60,15 +49,15 @@ When tackling pipelined designs, for a software-visible state variable \(e.g., a ```javascript "state mapping": { ..., - "r1" : [ {"cond":"m1.reg_1_w_stage[1]", "map":"ex_alu_result"}, - {"cond":"m1.reg_1_w_stage[0]", "map":"ex_wb_val"}, - {"cond":null, "map":"register[1]"} ], + "r1" : [ [ "m1.reg_1_w_stage[1]", "ex_alu_result"], + [ "m1.reg_1_w_stage[0]", "ex_wb_val" ], + [ "1'b1", "register[1]" ]], "r2" : [...], ... } ``` -**Light-weight flushing.** This is a setting similar to what has been used in ARM's ISA-Formal work. One can use prophecy variables \(variables holding values available in the future\) to help construct the mapping. The value-on-the-fly will be written back to the architectural register file in the future and we can map a register with that future value. Our variable mapping allows this mapping using what we call "value holder" \(it is essentially an auxiliary variable and note that it can also hold history values\). The light-weight flushing setting is illustrated in the figure below: +**Light-weight flushing.** This is a setting similar to what has been used in ARM's ISA-Formal work. One can use prophecy variables \(variables holding values available in the future\) to help construct the mapping. The value-on-the-fly will be written back to the architectural register file in the future and we can map a register with that future value. Our variable mapping allows this mapping using what we call "value recorder" \(it is essentially an auxiliary variable and note that it can also hold history values\). The light-weight flushing setting is illustrated in the figure below: ![](../.gitbook/assets/future-values.png) @@ -77,191 +66,23 @@ Again for the previous pipeline example, we can have the variable mapping as fol ```javascript "state mapping": { ..., - "r1" : [ {"cond":"__START__", "map":"#valueholder_r1#"}, - {"cond":"__IEND__", "map":"register[1]"}], + "r1" : [ ["#decode#", "( m1.register[1] )@( stage_tracker == 1 )"], + ["#commit#", "register[1]"]], "r2" : [...], ... } ``` -Here `#` quoted names are the names to value holders. The condition `__START__` indicates, at the beginning of the instruction under verification, `r1` is mapped to the value holder \(a future value in our case\) and at the end of the instruction execution \(indicated by `__IEND__`\), it is mapped to the write-back value in the register file. - -Value holders are defined in the `value-holder` section in the variable mapping file. Below is an example. The condition here indicates when to take the value of `m1.register[1]` and hold it for use universally. `stage_tracker` is an example of the monitor that one may add to track the stage of an instrcution in the pipeline \(if the original design already has some tracking mechanism, it can be used instead\). - -```javascript -"value-holder": { - "valueholder_r1":{ - "cond" : "stage_tracker == 1", // Commit point of the previous instruction - "val" : "m1.register[1]", - "width": 8 - } -} -``` - -{% hint style="info" %} -`width` in the above example can be set to `"auto"` which will allow the tool to automatically determine the width of the value holder. -{% endhint %} - -{% hint style="info" %} -We are working on a syntactic sugar in the form of `val@cond` in the `state-mapping` part which can automatically generate a value holder. In the future we shall allow the following shortcut: - -```javascript - "state mapping": { - ..., - "r1" : [ {"cond":"__START__", "map":"register[1] @ (stage_tracker == 1)"}, - {"cond":"__IEND__", "map":"register[1]"}], - "r2" : [...], - ... - } -``` -{% endhint %} - -## Stage Tracker - -As shown by the previous example, it is very often that one would like to track the stage of an instruction. Currently this is done via inline Verilog monitors. For the previous example, we have a monitor like the following. - -```javascript - "verilog-inline-monitors" : { - "stage_tracker" : { - "verilog": - ["always @(posedge clk) begin", - " if (__START__) stage_tracker <= 0;", - " else if (__STARTED__ && !__ENDED__) stage_tracker <= stage_tracker + 1;", - "end"], - "defs" :[ ["stage_tracker", 2, "reg"] ], - "refs" :[] - } -``` - -This monitor starts the tracking when the instruction under verification starts to execute and counts up till the instruction finishes. This works for the simple case as the pipeline will not stall and the tracker does not need to stall either. However, in general this is not true and below we provide an example to handle a more general case. - -In the example below, there are 3 intermediate stages and a final write-back \(s4\) stage. The monitor here uses the signals inside the pipeline like `m1.s1_to_s2$D_IN` and `m1.s1_to_s2$EN` to tell if the current instruction moves to the next stage. These are indicated by the signals like `s1_to_s2`. - -```javascript - "verilog-inline-monitors" : { - "stage_tracker" : { - "verilog": - [ - "wire s1_begin = m1.stage1_rg_full;", - "wire s1_to_s2 = m1.s1_to_s2$D_IN & m1.s1_to_s2$EN;", - "wire s2_to_s3 = m1.s2_to_s3$D_IN & m1.s2_to_s3$EN;", - "wire s3_to_s4 = m1.s3_deq$EN & m1.s3_deq$D_IN;", - "always @(*) begin monitor_s1 = s1_begin & ~monitor_s1_already & __START__; end", - "always @(posedge clk) begin", - " if(rst)", - " monitor_s1_already <= 0;", - " else if (monitor_s1 && monitor_s2_nxt)", - " monitor_s1_already <= 1;", - "end", - "always @(*) begin monitor_s2_nxt = (monitor_s2 == 0) ? ( s1_to_s2 & monitor_s1 ? 1'b1 : 1'b0) : ", - " ( s2_to_s3 ? 1'b0 : 1'b1); end", - "always @(posedge clk) begin", - " if(rst) begin", - " monitor_s2 <= 0;", - " monitor_s2_already <= 0;", - " end", - " else begin", - " monitor_s2 <= monitor_s2_nxt;", - " if (monitor_s2 & monitor_s3_nxt)", - " monitor_s2_already <= 1;", - " end", - "end", - "always @(*) begin monitor_s3_nxt = (monitor_s3 == 0) ? ( s2_to_s3 & monitor_s2 ? 1'b1 : 1'b0) : ", - " (s3_to_s4 ? 1'b0 : 1'b1) ; end ", - "always @(posedge clk) begin", - " if(rst) begin", - " monitor_s3 <= 0;", - " monitor_s3_delay <= 0;", - " end", - " else begin", - " monitor_s3 <= monitor_s3_nxt;", - " if (monitor_s3)", - " monitor_s3_delay <= 1'b1; // enough", - " end", - "end", - "always @(*) begin monitor_s4_nxt = ", - " monitor_s3 && s3_to_s4 ? 1'b1 : monitor_s4; end", - "always @(posedge clk) begin", - " if(rst) begin", - " monitor_s4 <= 0;", - " monitor_s4_delay <= 0;", - " end", - " else begin", - " monitor_s4 <= monitor_s4_nxt;", - " if (monitor_s4)", - " monitor_s4_delay <= 1'b1;", - " end", - "end", - "always @(*) begin end_of_pipeline = monitor_s4 && ~monitor_s4_delay ; end // just check one cycle" - ], - "defs" : - [ - ["end_of_pipeline" , 1 , "reg"] , - ["monitor_s1_already" , 1 , "reg"] , - ["monitor_s1" , 1 , "reg"] , - ["monitor_s1_delay" , 1 , "reg"] , - ["monitor_s2" , 1 , "reg"] , - ["monitor_s2_nxt" , 1 , "reg"] , - ["monitor_s2_already" , 1 , "reg"] , - ["monitor_s3" , 1 , "reg"] , - ["monitor_s3_nxt" , 1 , "reg"] , - ["monitor_s3_delay" , 1 , "reg"] , - ["monitor_s4_nxt" , 1 , "reg"] , - ["monitor_s4" , 1 , "reg"] , - ["monitor_s4_delay" , 1 , "reg"] - ] , - - "refs" :[ - "m1.stage1_rg_full", - "m1.s1_to_s2$D_IN", - "m1.s1_to_s2$EN", - "m1.s2_to_s3$D_IN", - "m1.s2_to_s3$EN", - "m1.s3_deq$D_IN", - "m1.s3_deq$EN", - "m1.rg_retiring$EN" ] - }// stage tracker - } -``` - -{% hint style="info" %} -As the tracking of pipeline stages is a very common scenario, we are also working on a template to automatically generate a pipeline stage tracker. We expect this to handle the case of branching pipelines \(where there are fan-out points to dispatch instructions through any of the downstream pipelines, and merge point that coalesce the end of multiple pipelines\). Events are specified based on their effects on the stages as `exit` event and `enter` event. We shall also allow caching temporary values in auxiliary variables at the time of the events. -{% endhint %} - -## Simple Delays - -Another common scenario is that we'd like to delay a signal for a few cycles. The general way for this is an inline-monitor. For example, we'd like to delay `xram_ack` for one cycle and use it as the finish condition for an instruction. First, we can have a few lines in `verilog-inline-monitors` section as follows: - -```javascript -"verilog-inline-monitors" : { - "xram_ack_delay_1" : { - "verilog": [ - "always @(posedge clk) begin xram_ack_delay_1 <= xram_ack; end" - ], - "defs" : [["xram_ack_delay_1" , 1 , "reg"]], - "refs" : ["xram_ack"] - } -} -``` - -Recall that `defs` contains the auxiliary variables that we'd like to create and `refs` are the signals in the original design that we use in the monitor. - -{% hint style="info" %} -We are working on a syntactic sugar in the form of `signal ## cycle` and `(expression) ## cycle` that will create verilog-inline-monitor automatically to delay a signal for the given number of cycles. -{% endhint %} +Here `#` quoted names are the names of the phases. The condition `#decode#` indicates, at the beginning of the instruction under verification, `r1` is mapped to the value recorder \(a future value in our case\) and at the end of the instruction execution \(indicated by `#commit#`\), it is mapped to the write-back value in the register file. ## Mapping of Memory The specification of memory state variable mapping can be very different depends on the types of memory. -The memory in Verilog be internal or external. While the memory in ILA may be modeled as an internal or memory state variable, as well. -There isn't a strict dependency between the two choices. And there are four combinations as described below. +The memory in Verilog can be internal or external. While the memory in ILA may be modeled as an internal or memory state variable, as well. Therefore, there are four combinations as described below. ### Internal Memory in both ILA and RTL -Currently, there isn't a uniform and scalable way to handle this case for both Pono and JasperGold. -The current implemented approach is to declare the memory as internal in the annotation section, however, this won't scale to large memory. -Below gives an example. - +In this case, you can use the array expression in `state mapping` section to match the arrays. Let's see an example. The implementation contains two internal memories `mema` and `memb`, when `start` signal is asserted, it will swap the contents between two addresses in these two memories, where the addresses are specified by the input indices. ```text @@ -311,29 +132,17 @@ The ILA model also model these as internal memory state variables and the ILA ha } ``` -The mapping of the memories in ILA and Verilog is very straight-forward (below only shows the `state mapping` section). +The mapping of the memories in ILA and Verilog is very straight-forward: ```javascript "state mapping": { - "mema":"mema", - "memb":"memb"}, + "mema":"RTL.mema", + "memb":"RTL.memb"}, ``` -This simple handling will work for all backends, but would not scale to large memories. -If it is possible to convert the internal memory to an external one by commenting away the declaration of the Verilog array and the associated read/write logic, then we can use the memory abstraction approach that applies to external memory. (Note in the conversion, please keep the read/write signals intact as they will be treated as if they are interface signals to the external memory, and our tool can automatically pull these signals to the top level module.) - +In the backend, model checker like Pono will use array theory to handle the properties. However for JasperGold, the array will be kept concrete and would not scale to large memories. +If it is possible to convert the internal memory to an external one by commenting away the declaration of the Verilog array and the associated read/write logic, then we can use the interface mapping approach that applies to external memory. (Note in the conversion, please keep the read/write signals intact as they will be treated as interface signals to the external memory, and our tool can automatically pull these signals to the top-level module.) -{% hint style="info" %} -Currently, there is a limitation on the memory abstraction model, which only supports making one read and one write concrete. So, if the internal array is read or written more than twice during the execution of the instruction and they must be concrete to avoid the spurious counterexample due to the abstraction, you might have to consider the commercial solution (the Proof Accelerator in JasperGold, which is essentially a memory abstraction but can be configured to support multiple concrete read and write). -{% endhint %} - -{% hint style="info" %} -Specifically, for the Pono backend, we are working on a solution to use SMT array theory to support mapping of arrays. However, although no Verilog modification is needed, it might be difficult for the model checkers to prove unbounded correctness. -{% endhint %} - -{% hint style="info" %} -We are also considering the possibility of intergrating CHC solvers to overcome the above difficulty when handling arrays. Comments and feedbacks on this are greatly appreciated. -{% endhint %} ### Internal Memory in ILA and External Memory in RTL @@ -362,23 +171,22 @@ module swap ( endmodule ``` -Below shows the signal mapping below. Here it is a bit tricky as in Verilog there is no such signal that holds the output of the -read from these two arrays (they are directly used to overwrite the contect in another location). So we will need to create auxiliary variables to support this. In the table, we use `#mema_rdata#` and `#memb_rdata#` as the place-holders. +Below shows the signal mapping below. Here it is a bit tricky as in Verilog there is no such signal that holds the output of the read from these two arrays (they are directly used to overwrite the contect in another location). So we will need to create auxiliary variables to support this. In the table, we use `mema_rdata` and `memb_rdata` as the place-holders. | memory.port | signal | |------------- |-------------- | -| mema.ren | start | -| mema.raddr | addra | -| mema.rdata | #mema_rdata# | -| mema.wen | start | -| mema.waddr | addra | -| mema.wdata | #memb_rdata# | -| memb.ren | start | -| memb.raddr | addrb | -| memb.rdata | #memb_rdata# | -| memb.wen | start | -| memb.waddr | addrb | -| memb.wdata | #mema_rdata# | +| mema.ren | RTL.start | +| mema.raddr | RTL.addra | +| mema.rdata | mema_rdata | +| mema.wen | RTL.start | +| mema.waddr | RTL.addra | +| mema.wdata | memb_rdata | +| memb.ren | RTL.start | +| memb.raddr | RTL.addrb | +| memb.rdata | memb_rdata | +| memb.wen | RTL.start | +| memb.waddr | RTL.addrb | +| memb.wdata | mema_rdata | The overall state variable mapping should looks like this: @@ -388,35 +196,37 @@ The overall state variable mapping should looks like this: "models": { "ILA":"m0" , "VERILOG": "m1" }, "instruction mapping": [], "state mapping": { - "mema":"**MEM**mema", - "memb":"**MEM**memb"}, - - "interface mapping": { - "rst":"**RESET**", - "clk":"**CLOCK**", - "addra":"addra", - "addrb":"addrb", - "start":"start" + "mema": + { + "ren" : "RTL.start" , + "raddr" : "RTL.addra" , + "rdata" : "mema_rdata", + "wen" : "RTL.start" , + "waddr" : "RTL.addra" , + "wdata" : "memb_rdata" + }, + "memb": + { + "ren" : "RTL.start" , + "raddr" : "RTL.addrb" , + "rdata" : "memb_rdata", + "wen" : "RTL.start" , + "waddr" : "RTL.addrb" , + "wdata" : "mema_rdata" + } + }, + "input mapping": { + "addra":"RTL.addra", + "addrb":"RTL.addrb", + "start":"RTL.start" }, - "annotation" : { - "memory-ports" : { - "mema.ren" : "start" , - "mema.raddr" : "addra" , - "mema.rdata" : "#mema_rdata#" , - "mema.wen" : "start" , - "mema.waddr" : "addra" , - "mema.wdata" : "#memb_rdata#" , - "memb.ren" : "start" , - "memb.raddr" : "addrb" , - "memb.rdata" : "#memb_rdata#" , - "memb.wen" : "start" , - "memb.waddr" : "addrb" , - "memb.wdata" : "#mema_rdata#" - } + "RTL interface connection": { + "RESET" : "rst", + "CLOCK" : "clk" }, - "verilog-inline-monitors" : { + "monitor" : { "read_value_holder" : { "verilog": [], "defs" :[ ["mema_rdata", 8, "wire"],["memb_rdata", 8, "wire"] ], @@ -426,14 +236,6 @@ The overall state variable mapping should looks like this: } ``` -And to aid efficient reasoning, you should also enable `MemAbsReadAbstraction` option in the configuration for `VerilogVerificationTargetGenerator`. An example is given below: - -```cpp - VerilogVerificationTargetGenerator::vtg_config_t vtg_cfg; // default configuration - vtg_cfg.MemAbsReadAbstraction = true; // enable read abstraction in the abstract memory model - VerilogVerificationTargetGenerator vg( ... /* the arguments are omitted here */ , - vtg_cfg); // give vtg_cfg as the extra configuration -``` ### External Memory in ILA and Internal Memory in RTL @@ -442,7 +244,7 @@ In this case, you may want to consider to convert the internal Verilog memory as ### External Memory in both ILA and RTL In this case, you can try to map the directly interface signals between ILA and RTL, if -you are unable to write it as an one-to-one mapping in `interface mapping` section, `mapping control` section is available for you. +you are unable to write it as an one-to-one mapping in `input mapping` section, you can also use `additional mapping` section to specify the relation between the two sets of interfaces. diff --git a/verification/refinement.md b/verification/refinement.md index 690eeeb..7b1f5fb 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -1,228 +1,292 @@ # Refinement Relation -The refinement map or refinement relation mainly consists of two parts: _variable mappings_ and _instruction completion conditions_. These two parts are specified in two separate files, one referred as _var-map_ and the other _inst-cond_. +## General Information -Besides the above two parts, there are other auxiliary information needed. They are: +Refinement relation is specified in JSON format and is provided as two files, one referred to as _variable mappings_ and the other as _instruction completion conditions_. +The JSON format allows specifying data structures like map and list and support datatypes like string, integer and `null` (for empty field). -* **module naming**: The names of the ILA module and the Verilog module. -* **global invariants**: Some properties that are globally true for the Verilog design that will be checked separately and can be safely assumed when verifying individual instructions. -* **interface signal information**: What does the interface of the Verilog top module look like and what do these signals mean to the tool. -* **uninterpreted function mapping**: What an uninterpreted function inside the ILA model corresponds to. +A map (similar to a dictionary in Python) has the following syntax: +```javascript +{ + // a map is a set of key-value pairs + // the key must be string in "" + // the value can be anything + "a-string-for-key" : "a-string-for-value", + "a-string-for-another-key" : 123, + "a-string-for-a-third-key" : ... +} +``` + +A list is an ordered set of elements, where each element can be any string, integer, or nested data structures. JSON format does not require the elements are of the same type. +In the top-level of a JSON file is a map and we call the key-value pairs in this top-level map as sections. -## The Structure of Variable Mappings +## The Structure of Variable Mapping + +Below shows the general structure the variable mapping file (or in short, var-map). Each section (like `state mapping"`) will be explained in detail later. Section `additional mapping`, `assumptions`, `monitor` and `functions` are optional. Section names are case-insensitive and you can always use hypen (`-`) to replace space in the section names. ```javascript { - "models": { - "ILA" : "" , - "VERILOG": "" - }, "state mapping": { - "" : "", + "" : "", // more ... }, - "interface mapping": { - "" : "", + "input mapping": { + "" : "", // more ... - }, - "mapping control": [ - "", + }, + "RTL interface connection" :{ + "CLOCK" : { + "" : "", // an input or a list of inputs + "" : ["", ""] }, + "RESET" : "", // an input or a list of inputs + "NRESET" : "", // an input or a list of inputs + "CUSTOMRESET" : "", // an input or a list of inputs + } + "additional mapping": [ + "", // more ... ], - "functions":{ + "assumptions": [ + "", + // more ... + ], + "monitor" : { + "" : { + "template" : "phase tracker", + ... + // instantiate a phase tracker template + // each template has its other fields + // to fill in + }, + "" : { + "template" : "value recorder", + ... + // instantiate a value recorder + // c,v,w + + }, + "" : { + "verilog" : "", + ... + // directly writing verilog here + }, + ... + } + "functions":{ // for uninterpreted functions "": [ [ - "", "", - "", "", + "", "", + "", "", // more ... - ] + ], + ... ] } } ``` -## The Structure of Instruction Completion Conditions -```javascript -{ - "instructions": - [ - { - "instruction" :"", - "ready bound" :12345, // - "ready signal" :"", - "max bound" :12345, // - "start condition" :"", - "flush constraint":"", - "pre-flush end" :"", - "post-flush end" :"" - } - ] -} -``` +## Refinement Expression, Condition and Signal Names -## Module Naming +In the above general structure, you can find terms like "refinement expression", "condition" or "signal name". Refinement expressions are basically valid Verilog expressions with some minor differences. We introduce new syntax for value recorder, delay expression and phase identifiers, and these will be explained in the later sections of this document. +The Verilog expressions can be interpreted as either (1) the expression of a function which specifies how ILA architectural state variable can be computed from the Verilog signals or (2) a relation between ILA architectural state variable and RTL signals. The difference in the interpretation is determined by whether the expression is a predicate in the last level. For example, a expression `RTL.v1 + RTL.v2` is not a predicate, whereas `ILA.v1 == RTL.v1 + RTL.v2` is a predicate. Whether the refinement expression is regarded as a predicate, is independent from its bit-width. For example `RTL.one_bit_signal` is not a predicate, even it is one-bit wide, whereas `RTL.one_bit_signal == 1'b1` is a predicate. -The module naming section comes first in the _var-map_ JSON file. It is a dictionary \(map\) with two elements. One element should have the key `ILA` and the value of it is what will be used as the instance name of the ILA module. The other element should have the key `VERILOG` with the value to be the instance name of the Verilog module. These names are used in all the expressions later when you want to refer to a variable in Verilog or ILA. +"Condition" is similar to a "refinement expression" as it follows the same syntactic requirements. However, the type or the outcome of a condition must be 1-bit. Even if it is not in the form of a predicate, it will be interpreted as a predicate (by implicitly adding `xxx == 1'b1` in the top-level). -## Variable Mapping +"Signal name" refers to a single signal (in RTL) and you cannot have any computation there. -The variable mapping in the JSON file is a map data structure. The keys of this map are the state variable names in the ILA model while the values are the Verilog variables. There are cases that one Verilog state variable can be mapped to multiple Verilog state variables and the mapping may be some special function. So the allowed value field of this map can be: -1. A Verilog variable name as a string. If the Verilog variable is in the top module of Verilog, you can omit the module name \(it does not hurt to add it\). Otherwise, you must specify the complete hierarchy. For example, if you want to refer to a signal `S` in module `A` that is instantiated with name `IA` in the top module, while the top module's instance name is `VERILOG` \(specified in the previous section\), then you should use `VERILOG.IA.S` to refer to it. -2. A predicate that has at least a `=` in it \(you can use `>=` , `<=` , `==` and etc.\) This is just for our parser to distinguish it from the first case. -3. A string-string pair that is in the form of a list or map. If it is given as a list, the first element is regarded as the condition and the second element is regarded as the mapping. It conveys the meaning of "when the condition is true, the ILA and Verilog variables should have the mapping". If the condition is not true, there is no mapping guaranteed. If the string-string pair is given as a map, it must have two elements. One element should have the key `cond` and the other should have the key `map`. The `map` part could be a string of Verilog variable name as in case \(1\) or a Verilog expression as case \(2\). -4. A list of string-string pairs, each pair follows requirement in \(3\). -5. If the ILA variable on the left is a memory, the right side depends on whether the Verilog memory is internal or external. If inside Verilog, there is an array that corresponds to this memory, you can directly use this name on the right side. Otherwise, you can make this ILA memory to map with an external memory using `"ILA-mem-name":"**MEM**ILA-mem-name"`. +## Special Syntax in Refinement Expressions -Below are some of the examples: +### Value Recorder -```javascript -{ - "state mapping": { - "ILA_state_1" : "Verilog_state_1", // case 1 - "ILA_state_2" : "ILA_state_2 == Verilog_state_2 + Verilog_state_3", // case 2 - "ILA_state_3" : ["__START__", "Verilog_state_3"], // case 3.a - "ILA_state_4" : { "cond":"__START__", "map":"Verilog_state_4"}, // case 3.b - "ILA_state_5" : [["__START__", "Verilog_state_5"], ["__IEND__","Verilog_state_6"]], // case 4 - "ILA_mem_state" : "Verilog_array_name", // case 5.a : internal memory in Verilog - "ILA_mem_state" : "**MEM**ILA_mem_state", // case 5.b : external memory in Verilog - // more ... - }, - // other fields ... -} -``` +Value holder is one special kind of auxiliary variables and can be introduced to capture the value of a Verilog variable at a certain time or under a certain condition. This is different from directly creating an auxiliary register in RTL. The value of a RTL register is not available for use before it is assigned under the conditionm, +whereas, the content of a value holder is globally available even before the clock cycle where the specified condition is true. This is achieved with the help of assumptions. -The corresponding generated assumptions will be in the following form: +The following syntax is used to make a value recorder: `value @ condition`, where each of the value and condition part can be RTL signals or expressions. If either the `value` or `condition` is more than a signal name, paranthesis is needed, like `( RTL.v1 + RTL.v2 ) @ RTL.s1.commit`. +Nested value recorder (value recorders in `value` or `condition`) is not allowed. -```text -wire __m10__ = Verilog_state_1 == __ILA_SO_ILA_state_1 ; -wire variable_map_assume___p1__ILA_state_1 = (~ __START__) || (__m10__) ; // __START__ --> Verilog_state_1 == __ILA_SO_ILA_state_1 +### Simple Delay -wire __m12__ = Verilog_state_2 + Verilog_state_3 == ILA_state_2 ; -wire variable_map_assume___p3__ILA_state_2 = (~ __START__) || (__m12__) ; +You can delay a signal by a fixed number of cycles using `signal ## cycle`. For example, if you need the value of signal `RTL.v1` one cycle after `RTL.s1.commit` becomes true for mapping, then you can write `RTL.v1 @ (RTL.s1.commit ## 1)` -wire __m14__ = (~ __START__ ) || ( Verilog_state_3 == ILA_state_3 ) ; -wire variable_map_assume___p5__ILA_state_3 = (~ __START__) || (__m14__) ; +### Phase Identifier -wire __m16__ = (~ __START__ ) || ( Verilog_state_4 == ILA_state_4 ) ; -wire variable_map_assume___p7__ILA_state_4 = (~ __START__) || (__m16__) ; +If the RTL executes the instructions in multiple phases (e.g., pipeline stages), you will need to declare these phases in order to track the progression of the instruction and to find out its time of finish. This create phases identifiers. +By default, there are two built-in phases identifiers: `#start#` and `#end#`. +Generally speaking, the phase identifier are those wrapped in two `#`. +The specification of stages will be explain [later](#template-for-phase-identifier). -wire __m18__ = ( (~ __START__ ) || ( Verilog_state_5 == ILA_state_5 ) ) && ( ~( ~__START__ && __IEND__ ) || Verilog_state_6 == ILA_state_5 ) ; // __START__ --> match1 && (~__START__ && __IEND__) --> match2 -wire variable_map_assume___p9__ILA_state_5 = (~ __START__) || (__m18__) ; +## Module Naming -// map to an internal Verilog array : element-wise equality -assign __m20__ = ( __ILA_SO_mem_0 == VerilogArray_0_)&&( __ILA_SO_mem_1 == VerilogArray_1_)&&... ; -assign variable_map_assume___p11__ = (~ __START__ )|| (__m20__) ; +By default, when you refer to signal in RTL, you can use something like `RTL.module_instance_name1.module_instance_name2.signal` to refer to it. And if you use a variable (either input or state variable) in ILA, you can use the format `ILA.var_name`. If you want to override this default, you can write a `model name` section in the variable mapping to rename. + +```javascript + +"model names" : { + "ILA" : "SomeNameHere", + "RTL" : "SomeNameHere" +} -// map to an external Verilog array : using memory abstraction -// no assumption is needed ``` -and the assertions: +## State Mapping and Input Mapping -```text -wire __m0__ = Verilog_state_1 == __ILA_SO_ILA_state_1 ; -wire variable_map_assert___p1__ILA_state_1 = (~ __IEND__) || (__m0__) ; // IEND --> Verilog_state_1 == __ILA_SO_ILA_state_1 +The state mapping in the JSON file is a map data structure. The keys of this map are the state variable names in the ILA model while the value of the map can be (1) a refinement expression, (2) a list of condition-refinement expression pairs for conditional mapping (a pair is written as a list of two elements) (3) a memory expression for mapping internal array in RTL, or (4) a map following a pre-defined template for external memory. And below shows the syntactic structure of state mapping: -wire __m2__ = Verilog_state_2 + Verilog_state_3 == ILA_state_2 ; -wire variable_map_assert___p3__ILA_state_2 = (~ __IEND__) || (__m2__) ; +```javascript +{ + "state mapping": { + "ILA_bitvec_state_var_1" : "", // case 1 + "ILA_bitvec_state_var_2" : [ + ["", ""], + ["", ""]], // case 2 + "ILA_mem_state_var_1" : "", // case 3 : internal RTL memory + "ILA_mem_state_var_2" : { // case 4 : external RTL memory + "wen" : "", + "waddr" : "", + "wdata" : "", + "ren" : "", + "raddr" : "", + "rdata" : "" + }, + // more ... + }, + // other fields ... +} +``` -wire __m4__ = (~ __START__ ) || ( Verilog_state_3 == ILA_state_3 ) ; -wire variable_map_assert___p5__ILA_state_3 = (~ __IEND__) || (__m4__) ; +For conditional mapping, there is a priority for the conditions. The first listed condition will be tested first, and if it is true, the first refinement expression will be used and then comes to the second and third. -wire __m6__ = (~ __START__ ) || ( Verilog_state_4 == ILA_state_4 ) ; -wire variable_map_assert___p7__ILA_state_4 = (~ __IEND__) || (__m6__) ; +A memory expression allows more than a Verilog array name, because sometimes, the mapping for array variables is one-to-one. We support conditional mapping in this case, which can specify in the similar syntax as case (2), or you can use ` conditon ? var1 : var2 `. In the future, we may support using universal quantifier with indices for more complex mapping of arrays. -wire __m8__ = ( (~ __START__ ) || ( Verilog_state_5 == ILA_state_5 ) ) && ( ~( ~__START__ && __IEND__ ) || Verilog_state_6 == ILA_state_5 ) ; // __START__ --> match1 && (~__START__ && __IEND__) --> match2 -wire variable_map_assert___p9__ILA_state_5 = (~ __IEND__) || (__m8__) ; +For an external memory, the mapping is actually between interface signals. The ILA array variables use 6 interface signals (see the table below) which should be mapped with the RTL signals. You can use refinement expression or condition-refinement pair for these signal mapping. Later, we shall see some examples of mapping internal or external arrays in ILA with either internal or external arrays in RTL. -// map to an internal Verilog array : element-wise equality -assign __m10__ = ( __ILA_SO_mem_0 == VerilogArray_0_)&&( __ILA_SO_mem_1 == VerilogArray_1_)&&... ; -assign variable_map_assert___p11__ = (~ __IEND__ )|| (__m10__) ; +| interface signals | meaning | +|------------- |-------------- | +| ren | read enable | +| raddr | read address | +| rdata | read data | +| wen | write enable | +| waddr | write address | +| wdata | write data | -// map to an external Verilog array : using memory abstraction -absmem #( - .AW(32), - .DW(8), - .TTS(4294967296) ) -mi0(..., .mem_EQ_(mem_EQ_) ); -assign variable_map_assert__p13__ = (~ __IEND__) || (mem_EQ_) ; -``` -One note in the above example: the condition can refer to special signals \(`__START__` and `__IEND__`\), which are the condition when the instruction-under-verification starts to execute and finishes. +And the `interface mapping` is similar but there the key names are the ILA input variables. Currently, input variables with array type are not supported. -## Instruction Completion Condition -The instruction completion condition is specified per instruction. In the JSON file, it is a list of maps. The list does not need to be a full list of instructions. Those not in the list will not be verified. Each dictionary must have an element whose key is `instruction` and the value of this element is the name of the instruction in the ILA model. Besides this name element, it must contain one of the `ready bound` or the `ready signal` element. The `ready bound` specifies a bound that the instruction takes. It is used for instructions that take a fixed number of cycles. Alternatively, one can provide a signal \(or a predicate\) in the `ready signal` field. -There are several optional fields. They are `start condition`, `max bound`, `flush constraint`, `pre-flush end` and `post-flush end`. +## Other Sections in Variable Mapping -The `start condition` field, if provided, should be a list of strings. Each string is a Verilog expression that acts as a predicate on the Verilog design. It can be used to constrain the Verilog implementation state, because usually there are more microarchitectural \(implementation states\) in the design. For the starting state of an instruction, these microarchitectural states should be `consistent` with the visible states in the ILA, and you can use this field to enforce the `consistency` at your discretion. You can use `$decode$` and `$valid$` to refer to the instruction's decode function or its ILA valid condition. +Within the same file of variable mapping, there are other sections: (1) clock and reset mapping, (2) clock and reset configuration, (3) uninterpreted function mapping, (4) additional mapping (5) assumptions and (6) RTL monitors. -The `max bound` can be used when `ready signal` field is provided. It provides an assumption that the condition that the `ready signal` field specified will occur in the given number of cycles, and this will limit the model checking to that bound. Usually this is used for the additional environment assumptions about the input \(for example, how many cycles at most there are for a request to be served with a response\). -The `flush constraint`, `pre-flush end` and `post-flush end` signals are used when using the flushing verification setting. For this verification setting, you can refer to [TODAES19](https://bo-yuan-huang.github.io/ILAng-Doc/todaes18.pdf) on the ILA-based verification or the [Burch-Dill's approach](https://dl.acm.org/citation.cfm?id=735662) on processor verification. +### Interface Mapping -## Global Invariants +The interface mapping is used to specify which input port(s) is/are clock or reset signals. An example is shown below. The `CLOCK` field is a map from the name of the clock to the input pins. If there is only one clock, you can provide either a single input pin or multiple pin names in list which will be connected to the same clock. For reset, you can choose among the active-high/active-low or custom reset patterns using `RESET`, `NRESET` or `CUSTOMRESET`. -In the verification of instructions, we do not assume the design starts from the initial states. This helps us to get a better guarantee of the instruction correctness when only bounded model checking is used. However, if there is no constraints on the starting state of an instruction, there might be spurious bugs just because the design starts from a state that it will never reach when started from the reset state. In order to avoid this false positive, we use global invariants to constrain on the starting state. These invariants help rule out some unreachable states and the tool will generate a separate target to check whether the provided invariants are globally true or not. These invariants should be provided as a list of strings, where each string is a Verilog predicate. In the future, we will exploit invariant synthesis techniques to help synthesize these invariants. -## Interface Signal Information +```javascript + "RTL interface connection": { + // below creates two clocks : clkA and clkB + // clkA is connected to wclk + // and clkB is connected to rclk and clk + "CLOCK" : { "clkA" : "wclk", "clkB" : ["rclk", "clk"] }, + // or "CLOCK" : "clk" , single clock -- single pin + // or "CLOCK" : ["wclk", "rclk"] , multiple input pins use + // the same single clock + "RESET" : "reset", // you can have a list of signals here + "NRESET" : ["nreset1", "nreset2"], // like this + "CUSTOMRESET" : {"name" : "input-pin", ...} + } +``` + -The Verilog module comes with a set of I/O signals and the tool needs to know how these signals should be connected. The `interface mapping` field is a map whose keys are the Verilog I/O signal names and whose values can be one of the following: -* An ILA input name. This means that the Verilog input signal corresponds to one ILA input. They must have the same encoding and bit-width. -* `**KEEP**` directive. Telling the tool to have a wire of the same name and to connect it as the verification wrapper I/O. -* `**NC**` directive, indicating that this port does not need to be connected. -* `**SO**` directive, indicating that this is actually a direct output from a visible state variable \(a state variable that is modeled in the ILA\). -* `**RESET**` or `**NRESET**` directive. Indicating that this signal is the reset signal, active-high or active-low \(we assume synchronous reset\). -* `**CLOCK**` directive, indicating that this is the clock signal. -* `**MEM**name.signal` directive, indicating this signal is the connection to an external/shared memory. The name part should be the ILA state variable name of the memory, and the signal part could be one of the following: `wdata`,`rdata`, `waddr`,`raddr`, `wen`, `ren`. If the signal does not directly correspond to the write/read data, write/read address, write/read enable signal, it should be specified as `**KEEP**`, you can specify the mapping using "annotation" which will be dicussed below. -For example, for a Verilog input signal `control`, the effects of applying different directives are: +### Clock and Reset Configuration -* An ILA input name, e.g., `c1`. The tool will check if ILA indeed has the input `c1` and the type is matched. The wire `__ILA_I_c1` will be created and will be connected to the input port `control`. -* `**KEEP**` directive. The tool will check if the signal is input or output and create an input/output wire named `__VLG_I_control` with the proper width and connect to the port. -* `**NC**` directive. The tool will have it unconnected like `.control()`. -* `**SO**` directive. The tool will check if it is indeed an output and create an output wire `__VLG_SO_control` and connect to the port. In this example, because it is actually an input, the tool will give warning. -* `**RESET**` or `**NRESET**`. It will be connected as `.control(rst)` or `.control(~rst)`, where `rst` is the reset signal of the wrapper. -* `**CLOCK**` directive. It will be connected as `.control(clk)`, where `clk` is the clock signal of the wrapper. -* `**MEM**name.signal`. The tool will check if `name` is an ILA memory name. It will be connected as `.control(__MEM_name_0_signal)`. +In the interface mapping part, the clock and reset pins are specified. If there is one clock and the reset sequence is just one cycle, you don't need to explicitly state the clock and reset configurations. -## Notes on Memory State Variable +In the `reset` section, you can specify (1) the initial state (2) the length of the reset sequence, and (3) the custom reset sequence. A sequence is list of 0s or 1s. You can duplicate a sequence by adding a `"*N"` element in the end, where `N` is the number of copies to make. If you don't need reset sequence, you can set `cycles` to 0. And if both reset sequence and the initial state are provided, the RTL design will go through a reset sequence after the specified initial state. -Memory state variable might be internal or external to the module. An internal memory variable corresponds to a verilog array, and therefore no specific I/O interface is needed to access the memory. An external memory is a memory that connects with the current module via I/O interface. By default, all memory variables in the ILA are treated as external memory. The default setting can be override by _annotation_ in refinement map, and here is an example: +An example of the `reset` section is provided below. ```javascript - "annotation" : { - "memory" : { - "rf":"internal", - "mem":"external" - } - } + "reset" : { + "initial-state" : { + // this can be used with/without the reset sequence + "RTL.v1" : "1'b1", + "RTL.v2" : "2'b01", + ... + }, + "cycles" : 5, + // or 1 by default, this affects RESET, NRESET, CUSTOMRESET.n + // if you don't need reset, use 0 here + "custom-seq" : {"CUSTOMRESET.1": [0 , [1, "*3"], [0, "*1"] ] } +} ``` -The above annotation specifies memory named as `rf` and `mem` as internal and external respectively. Being internal or external affects how properties are generated. The mapping of internal memory is element-wise with expressions comparing two verilog arrays entry by entry, which is inefficient for a large memory. The mapping of external memory will use memory abstraction, which is more efficient. \(In the future, we will support mapping internal memory using the Array data-type of the underlying property verifier.\) +The `clock` section is only needed if you have multiple clocks. Currently, the tool will only handle the case where the frequency of the clock signals have a least common multiple. Therefore, they can be simulated using a single clock signal. The `clock` tells the tool how to simulate this clock signal. +This can be specified using either `custom` or `factor` field. The `custom` field are sequences 0s and 1s where you can use the similar duplicate operator as in the custom sequence of reset configuration. Alternatively, you can use the `factor` section to specify how many cycles of 0s and 1s and the starting offset of each clock. + + +An example of the `clock` section is provided below, where using the `factor` field and the `custom` field actually creates the same set of clock signals. -For the external memory, it is likely that there isn't a one-to-one mapping between the module interface and the six signals required by the memory abstraction module: `wdata` (write-data) ,`rdata` (read-data), `waddr` (write-address),`raddr` (read-address), `wen` (write-enable), `ren` (read-enable). Therefore, we support specifying the mapping using the annotation here. An example of the syntax is given below. ```javascript - "annotation" : { - "memory-ports" : { - "MemoryName.port1" : "Verilog-expression-here", - "MemoryName.port2" : "Verilog-expression-here" - } - } + "clock" : + { + "factor" : { + "clkA" : { + "high" : 6 + "low" : 6 + // 12x gclk's period + }, + "clkB" : { + "high" : 2 + "low" : 1 + // 3x gclk's period + // duty cycle 2/3 + }, + "clkC" : { + "high" : 2 + "low" : 4, + "offset" : 3 + // 6x gclk's period + // duty cycle 1/3 + // 1 1 0 0 0 0 + // start:^ + // offset should be positive + } + // tool will calcuate the min length + // LCM(12,3,6) = 12 + } + } + + // Alternatively, you can use the custom field. + // Using both the factor and custom fields is + // not allowed. + "clock" : + { + "custom" : { + "length" : 12, + "clocks": { + "CLOCK.1": [ [1, "*6"], [0,"*6"] ], + "CLOCK.2": [ [1, 1, 0], "*4" ], + "CLOCK.3": [ [0, "*3"], [1, "*2"] , [0, "*4"] , [1, "*2"], 0 ] + } + } + } + ``` -In the above example, `MemoryName` should be the name of the memory state variable in ILA and `port1`, `port2` should be one of `wdata` (write-data) ,`rdata` (read-data), `waddr` (write-address),`raddr` (read-address), `wen` (write-enable), `ren` (read-enable). The Verilog expression after the colon represents how to use the Verilog signal to compute the interface signals. -Note that this kind of mapping assumes the ports of an abstract memory state can be represented as a function of solely the Verilog signals. If this is not feasible for the design you are looking at, you can use the additional mapping capability provided by `mapping control` section described later in this chapter. -## Uninterpreted Function Mapping +### Uninterpreted Function Mapping -The ILA model may use uninterpreted functions, however, in the verification, the tool must know the correspondence of this uninterpreted function in order to reason about the correctness. In the `functions` field of the _var-map_ JSON, a map should be provided if uninterpreted function is used in the ILA model. The keys of the map are the function names, with the values in a list. Each element of this list is for one application of this function. Per each function application, the tool needs to know the correspondence of the arguments/result in the Verilog and when that happens, this is like a condition/mapping pair, and it is specified as a list. The correspondence of the function result goes first followed by the arguments \(in the same order as the arguments in ILA function definitions\). +The ILA model may use uninterpreted functions, however, in the verification, the tool must know the correspondence of this uninterpreted function in order to reason about the correctness. In the `functions` field of the _var-map_ JSON, a list should be provided if uninterpreted function is used in the ILA model. +Each element of this list is for one application of this function. Per each function application, the tool needs to know the correspondence of the arguments/result in the Verilog. And this is specified with a map. The keys of the map are the function names, with the values also in a map containing `result` and `arg` fields. `result` field accepts a single refinement expression while `arg` accepts a list. For example in the ILA there is such specification @@ -231,59 +295,160 @@ For example in the ILA there is such specification instr.SetUpdate(state0, div(arg0, arg1) ); ``` -Then in the refinement map +Then in the refinement map, `div` is followed by a list of one element (because there is only one function application in ILA). ```javascript { "functions" : { - "div" : [ - ["cond1", "verilog-signal-result", "cond2", "verilog-signal-arg0", "cond3", "verilog-signal-arg1", ] + "div" : [ { + "result" : "", + "arg" : [ + // there are only two arguments in div + "", + "" + ] + } ] } } ``` -## Additional Mapping +### Additional Mapping -Sometimes, the mapping between Verilog variables and ILA state variables does not fit easily into the state mapping section. For example, you may need a customized mapping from the Verilog design's memory interface to the provided 6-signal memory interface. The AES case study provides an example of this. The Verilog design uses two signals `stb` and `wr` to indicate memory read and write enable, which are different from the `ren` and `wen` signals. Therefore a mapping can be provided as follows: +Sometimes, the mapping between Verilog variables and ILA state variables does not fit easily into the state mapping section. +In this case you specified additional mapping using `additional mapping` section. It takes a list of strings and each string should be a valid Verilog expression. This will be translated as assumptions, which only appear when verifying individual instructions and will not be used when checking or synthesizing starting state invariants. ```javascript -"mapping control" : [ - "( wr & stb) == __MEM_XRAM_0_wen" , - "(~wr & stb) == __MEM_XRAM_0_ren" +"additional mapping" : [ + "( RTL.wr & RTL.stb) == (ILA.m1 & ILA.m2)" , + "(~RTL.wr & RTL.stb) == (ILA.m2 & ILA.m3)" ] ``` -Assumptions in the `mapping control` section does not appear in the invariant or invariant synthesis target. - -## Additional Assumptions +### Additional Assumptions This section allows users to add additional assumptions in the verification. They can be, for example, an assumption about the module I/O. ```javascript "assumptions" : [ // the two inputs can not be both 1 - "! ( verilog_module.input1 & verilog_module.input2 )" + "! ( RTL.input1 & RTL.input2 )" ] ``` Assumptions in this section are in effect when verifying the instructions, the invariants and when synthesizing the invariants. -## Value Holder +### RTL Monitors + +RTL monitors are additional logic and states that are added to aid the specification of refinement mapping. +Our tool provides two templates (value recorder and phase tracker) and also allows arbitrary synthesizable Verilog to be used. + +#### Phase Tracker + +Phase tracker is a template for creating auxiliary variables to track the phase of an instruction. An example is shown below. +It defines 4 phases, and the rules of entering and exiting each phase is specified in the `rules` field. +For each phase, you can give it name, otherwise you can refer to it as `phaseX` where `X` is an index number starting from 1. +There are two phases that are implicitly declared, which are `#decode#` and `#commit#`. +The entering condition should explicitly have its previous stage in the conjunction. -Value holder \(a.k.a prophecy variables, auxiliary variables and etc.\) can be introduced to capture the value of a Verilog variable at a certain time \(or under a certain condition\). Below is an example of a value holder: ```javascript -"value-holder": { - "r1_pvholder" : { - "cond": "m1.write_enable == 1", - "val":"m1.registers[1]", + "monitor" : { + "tracker" : { // this is just a name + "template" : "phase tracker", + "phases" : 4, + "event-alias" : { // will be translated as creating 1-bit wire + "issue" : "SomeVerilogExpressionsHere", + // for example + "i2e" : "RTL.s2_to_s3 & RTL.s2_to_s3", + "e2c" : "RTL.s3_deq & RTL.s3_deq" + }, + "rules" : [ + { // 1 + "enter" : { + "event" : "issue & #decode#" + }, + "exit" : { + "event" : "i2e" + } + }, + { // 2, if you give it a name, then + "name" : "second_phase" + "enter" : { + "event" : "i2e & #phase1#" + }, + "exit" : { + "event" : "e2c" + // it is redundant to add & #phase2# + } + }, + { // 3 + "enter" : { // you can use the name elsewhere + "event" : "e2c & #second_phase#", + }, + "exit" : { + "event" : "e2c ## 1", + } + } + ] + // instantiate a phase tracker template + // each template has its other fields + // to fill in + } +``` + +Additionally, you can declare alias for events which can be referred to in the rules. You can also define auxiliary variables and update them using actions. Below shows an example of tracking a command/instruction through a FIFO. When the command/instruction enters the FIFO, we need to take down the write pointer of the FIFO (stored in auxiliary variable `fifo_ptr`) so that we can know when the command/instruction gets out of the FIFO. + + +```javascript + "monitor" : { + "TrackingThroughFifo" : { // this is just a name + "template" : "phase tracker", + "phases" : 2, + "aux-var" : [ ["fifo_ptr", "reg", 8] ], + "rules" : [ + { // 1 + "enter" : { + "event" : "RTL.fifo_wen & #decode# ", + "action" : "fifo_ptr <= RTL.fifo_wptr;" + }, + "exit" : { + "event" : "RTL.fifo_ren & RTL.fifo_rptr == fifo_ptr" + } + }, + { // 2 + "enter" : { + "event" : "RTL.fifo_ren & RTL.fifo_rptr == fifo_ptr & #phase1#" + }, + "exit" : { + "event" : "..." + } + } + ] + } + } +``` + +The phase tracker also allows specifying branching and convergence. This is useful, for example, in the verification of superscaler out-of-order processor implementation, where there are multiple pipelines and instructions can be dynamically dispatched to some processing pipelines. A phase can be referred to in other parts of the refinement specification using `#phase_name#`. + + +#### Value Recoder + +Value recorder can be created using `value @ condition` syntax in the refinement expressions. Alternatively, you can also create explicit value recorders. An example showing the syntax for specifying explicit value recorder is provided below. For the `width` field, you can also use `"auto"` to ask the tool to automatically infer the width needed to hold the value. + + +```javascript + "monitor" : { + "r1_pvholder" : { // this is just a name + "template" : "value recorder", + "cond": "RTL.write_enable == 1", + "val":"RTL.registers[1]", "width":8 - } -} + } + } ``` -The above value holder will be translated to the following Verilog code fragments in the Verilog. +The above value recorder will be translated into the corresponding Verilog below. ```text input [7:0] __r1_pvholder_init__; @@ -293,37 +458,83 @@ always @(posedge clk) begin if(rst) begin r1_pvholder <= __r1_pvholder_init__; end - else if(1) begin + else begin r1_pvholder <= r1_pvholder; end end -assume property ((m1.write_enable == 1) |-> ((r1_pvholder) == (m1.registers[1]))); +assume property ((RTL.write_enable == 1) |-> ((r1_pvholder) == (RTL.registers[1]))); ``` -It creates an auxiliary Verilog variable `r1_pvholder` which carries a undetermined value. Its value keeps the same all the time, and an assumption says this undetermined value is same as the specified value `m1.registers[1]`, under the condition that `m1.write_enable == 1`. This variables can be referenced in other sections by `#r1_pvholder#` \(this tells the tool not to find this signal name in the original Verilog design. The `width` part can also be a string `"auto"`, which tells the tool to automatically determine the width \(in case of failure, error will be prompted.\) This value holder does not check if there is only one cycle that `m1.write_enable == 1` holds. If there are multiple cycles that its condition holds, the assumption may overconstrain if `m1.registers[1]` should carry different values at these points. This situation should be avoided. +It creates an auxiliary Verilog variable `r1_pvholder` which carries a undetermined value. Its value keeps the same all the time, and an assumption says this undetermined value is same as the specified value `RTL.registers[1]`, under the condition that `RTL.write_enable == 1`. This variables can be referenced in other sections by `r1_pvholder`. This value holder does not check if there is only one cycle that `RTL.write_enable == 1` holds. If there are multiple cycles that its condition holds, the assumption may overconstrain if `RTL.registers[1]` should carry different values at these points. This situation should be avoided. -## Verilog Monitor -In the case that user may want to add customized auxiliary variables, we support inline monitors for this purpose. +#### Abitrary Verilog -An example is given as follows: +You can also add arbitrary synthesizable Verilog as the monitor. An example is given below: ```javascript - "verilog-inline-monitors" : { - "stage_tracker" : { + "monitor" : { + "counter" : { "verilog": ["always @(posedge clk) begin", - " if (__START__) stage_tracker <= 0;", - " else if (__STARTED__ && !__ENDED__) stage_tracker <= stage_tracker + 1;", + " if (RTL.signal_1) counter <= 0;", + " else if (RTL.signal_2 && ! RTL.signal_3) counter <= counter + 1;", "end"], - "defs" :[ ["stage_tracker", 2, "reg"] ], - "refs" :[] + "defs" :[ ["counter", 2, "reg"] ], + "refs" :[ "RTL.signal_1" , "RTL.signal_2", "RTL.signal_3" ] }, } ``` -This creates a 2-bit variable `stage_tracker` to track the number of cycles \(this is just for demoing the syntax of Verilog monitor, you can in fact use the embedded variable `__CYCLE_CNT__` to track the number of cycles\). Variables that should be accessible outside the monitor should be defined in the `defs` list with its name, bit-width and its type: `reg` or `wire`. Variables used only inside the monitor can be defined inside the `verilog` code list. Any variable inside the original Verilog, if referenced, should be put in the list of `refs`. This will help our tool to add auxiliary wires to connect them with the monitor. +This creates a 2-bit variable `counter` to count the number of cycles under a certain condition. Variables that should be accessible outside the monitor should be defined in the `defs` list with its name, bit-width and its type: `reg` or `wire`. Variables used only inside the monitor can be defined inside the `verilog` code list. Any variable inside the original Verilog, if referenced, should be put in the list of `refs`. This will help our tool to add auxiliary wires to connect them with the monitor. + +Monitors are normally only in effect when verifying instructions. If you want a monitor to appear also when verifying the invariants, you can add the `"keep-for-invariants":true` attribute in the monitor's description following the `defs` and `refs` attributes. + + + + +## Instruction Completion Condition + + + +The instruction completion condition is specified per instruction. In the JSON file, it is a list of maps. The list does not need to be a full list of instructions. Those not in the list will not be verified. Each dictionary must have an element whose key is `instruction` and the value of this element is the name of the instruction in the ILA model. Besides this name element, it must contain one of the `ready bound` or the `ready signal` element. The `ready bound` specifies a bound that the instruction takes. It is used for instructions that take a fixed number of cycles. Alternatively, one can provide a signal \(or a predicate\) in the `ready signal` field. + +There are two optional fields. They are `start condition`, `max bound`. + +The `start condition` field, if provided, should be a list of strings. Each string is a Verilog expression that acts as a predicate on the Verilog design. It can be used to constrain the Verilog implementation state, because usually there are more microarchitectural \(implementation states\) in the design. For the starting state of an instruction, these microarchitectural states should be `consistent` with the visible states in the ILA, and you can use this field to enforce the `consistency` at your discretion. You can use `$decode$` and `$valid$` to refer to the instruction's decode function or its ILA valid condition. + +The `max bound` can be used when `ready signal` field is provided. It provides an assumption that the condition that the `ready signal` field specified will occur in the given number of cycles, and this will limit the model checking to that bound. Usually this is used for the additional environment assumptions about the input \(for example, how many cycles at most there are for a request to be served with a response\). + + +### The Structure of Instruction Completion Condition + +The structure of the instruction completion condition is relatively simple as shown below. `max bound` and `start condition` are optional, and you can only choose one between `ready bound` and `ready signal`. + + +```javascript +{ + "instructions": + [ + { + "instruction" :"", + "ready bound" :12345, // + "ready signal" :"", + "max bound" :12345, // + "start condition" :"" + } + ], + + "global invariants" : + [ + "Verilog-expressions-here", + ... + ] +} +``` + +### Global Invariants + +In the verification of instructions, we do not assume the design starts from the initial states. This helps us to get a better guarantee of the instruction correctness when only bounded model checking is used. However, if there is no constraints on the starting state of an instruction, there might be spurious bugs just because the design starts from a state that it will never reach when started from the reset state. In order to avoid this false positive, we use global invariants to constrain on the starting state. These invariants help rule out some unreachable states and the tool will generate a separate target to check whether the provided invariants are globally true or not. These invariants should be provided as a list of strings, where each string is a Verilog predicate. -Value holders and monitors are normally only in effect when verifying instructions. If you want a monitor to appear also when verifying the invariants, you can add the `"keep-for-invariants":true` attribute in the monitor's description following the `defs` and `refs` attributes. From 23141afd0b5805290ee606385ef096872e71bbab Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 1 Nov 2021 13:47:20 +0800 Subject: [PATCH 23/26] refinment v2 --- verification/refinement.md | 75 ++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/verification/refinement.md b/verification/refinement.md index 7b1f5fb..e3ddae8 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -3,7 +3,7 @@ ## General Information Refinement relation is specified in JSON format and is provided as two files, one referred to as _variable mappings_ and the other as _instruction completion conditions_. -The JSON format allows specifying data structures like map and list and support datatypes like string, integer and `null` (for empty field). +The JSON format allows specifying data structures like map and list and support data-types like string, integer and `null` (for empty field). A map (similar to a dictionary in Python) has the following syntax: ```javascript @@ -17,12 +17,12 @@ A map (similar to a dictionary in Python) has the following syntax: } ``` -A list is an ordered set of elements, where each element can be any string, integer, or nested data structures. JSON format does not require the elements are of the same type. -In the top-level of a JSON file is a map and we call the key-value pairs in this top-level map as sections. +A list is an ordered set of elements, where each element can be any string, integer, or nested data structures. JSON format does not require the elements of a list to have the same type. +The top-level of a JSON file is a map and we call the key-value pairs in this top-level map as sections. ## The Structure of Variable Mapping -Below shows the general structure the variable mapping file (or in short, var-map). Each section (like `state mapping"`) will be explained in detail later. Section `additional mapping`, `assumptions`, `monitor` and `functions` are optional. Section names are case-insensitive and you can always use hypen (`-`) to replace space in the section names. +Below shows the general structure of the variable mapping file (or in short, var-map). Each section (like `state mapping"`) will be explained in details later. Section `additional mapping`, `assumptions`, `monitor` and `functions` are optional. Section names are case-insensitive and you can always use hypen (`-`) to replace space in the section names. ```javascript { @@ -70,15 +70,16 @@ Below shows the general structure the variable mapping file (or in short, var-ma ... // directly writing verilog here }, + "" : "" ... } "functions":{ // for uninterpreted functions - "": [ - [ - "", "", - "", "", + "": [ // list of invocation + { // an invocation is a map with `result` and `arg` + "result" : "", + "args" : { "", ...} // args // more ... - ], + }, ... ] } @@ -88,8 +89,8 @@ Below shows the general structure the variable mapping file (or in short, var-ma ## Refinement Expression, Condition and Signal Names -In the above general structure, you can find terms like "refinement expression", "condition" or "signal name". Refinement expressions are basically valid Verilog expressions with some minor differences. We introduce new syntax for value recorder, delay expression and phase identifiers, and these will be explained in the later sections of this document. -The Verilog expressions can be interpreted as either (1) the expression of a function which specifies how ILA architectural state variable can be computed from the Verilog signals or (2) a relation between ILA architectural state variable and RTL signals. The difference in the interpretation is determined by whether the expression is a predicate in the last level. For example, a expression `RTL.v1 + RTL.v2` is not a predicate, whereas `ILA.v1 == RTL.v1 + RTL.v2` is a predicate. Whether the refinement expression is regarded as a predicate, is independent from its bit-width. For example `RTL.one_bit_signal` is not a predicate, even it is one-bit wide, whereas `RTL.one_bit_signal == 1'b1` is a predicate. +In the above general structure, you can find terms like "refinement expression", "condition" or "signal name". Refinement expressions are basically valid Verilog expressions with some minor differences. We introduce new syntax for *value recorder*, *delay expression* and *phase identifiers*, and these will be explained in the later sections of this document. +The Verilog expressions can be interpreted as either (1) the expression of a function which specifies how ILA architectural state variables can be computed from the Verilog signals or (2) a relation between ILA architectural state variable and RTL signals. The difference in the interpretation is determined by whether the expression is a predicate in the last level. For example, a expression `RTL.v1 + RTL.v2` is not a predicate, whereas `ILA.v1 == RTL.v1 + RTL.v2` is a predicate. Whether the refinement expression is regarded as a predicate is independent from the bit-width. For example, `RTL.one_bit_signal` is not a predicate, even it is one-bit wide, whereas `RTL.one_bit_signal == 1'b1` is a predicate. "Condition" is similar to a "refinement expression" as it follows the same syntactic requirements. However, the type or the outcome of a condition must be 1-bit. Even if it is not in the form of a predicate, it will be interpreted as a predicate (by implicitly adding `xxx == 1'b1` in the top-level). @@ -100,35 +101,26 @@ The Verilog expressions can be interpreted as either (1) the expression of a fun ### Value Recorder -Value holder is one special kind of auxiliary variables and can be introduced to capture the value of a Verilog variable at a certain time or under a certain condition. This is different from directly creating an auxiliary register in RTL. The value of a RTL register is not available for use before it is assigned under the conditionm, +Value holder is one special kind of auxiliary variables and can be introduced to capture the value of a Verilog variable at a certain time or under a certain condition. This is different from directly creating an auxiliary register in RTL. The value of a RTL register is not available for use before it is assigned under the condition, whereas, the content of a value holder is globally available even before the clock cycle where the specified condition is true. This is achieved with the help of assumptions. -The following syntax is used to make a value recorder: `value @ condition`, where each of the value and condition part can be RTL signals or expressions. If either the `value` or `condition` is more than a signal name, paranthesis is needed, like `( RTL.v1 + RTL.v2 ) @ RTL.s1.commit`. -Nested value recorder (value recorders in `value` or `condition`) is not allowed. +The following syntax is used to make a value recorder: `value @ condition`, where each of the value and condition part can be RTL signals or expressions. If either the `value` or `condition` is more than a signal name, a pair of parantheses is needed, like `( RTL.v1 + RTL.v2 ) @ RTL.s1.commit`. +Nested value recorders (value recorders in `value` or `condition`) are not allowed. ### Simple Delay You can delay a signal by a fixed number of cycles using `signal ## cycle`. For example, if you need the value of signal `RTL.v1` one cycle after `RTL.s1.commit` becomes true for mapping, then you can write `RTL.v1 @ (RTL.s1.commit ## 1)` -### Phase Identifier +### Phase Trackers -If the RTL executes the instructions in multiple phases (e.g., pipeline stages), you will need to declare these phases in order to track the progression of the instruction and to find out its time of finish. This create phases identifiers. -By default, there are two built-in phases identifiers: `#start#` and `#end#`. -Generally speaking, the phase identifier are those wrapped in two `#`. +If the RTL executes the instructions in multiple phases (e.g., pipeline stages), you will need to declare these phases in order to track the progression of the instruction and to find out its time of finish. This requires using phases trackers. +By default, there are two built-in phase trackers: `#decode#` and `#commit#`. +It is recommended to wrapped the phase trackers in a pair of `#`. The specification of stages will be explain [later](#template-for-phase-identifier). ## Module Naming -By default, when you refer to signal in RTL, you can use something like `RTL.module_instance_name1.module_instance_name2.signal` to refer to it. And if you use a variable (either input or state variable) in ILA, you can use the format `ILA.var_name`. If you want to override this default, you can write a `model name` section in the variable mapping to rename. - -```javascript - -"model names" : { - "ILA" : "SomeNameHere", - "RTL" : "SomeNameHere" -} - -``` +When you refer to signal in RTL, you can use something like `RTL.module_instance_name1.module_instance_name2.signal` to refer to it. And if you use a variable (either input or state variable) in ILA, you can use the format `ILA.var_name`. ## State Mapping and Input Mapping @@ -156,9 +148,9 @@ The state mapping in the JSON file is a map data structure. The keys of this map } ``` -For conditional mapping, there is a priority for the conditions. The first listed condition will be tested first, and if it is true, the first refinement expression will be used and then comes to the second and third. +For conditional mapping, the list of conditions has a priority. The first listed condition will be tested first, and if it is true, the first refinement expression will be used and then comes to the second and third. -A memory expression allows more than a Verilog array name, because sometimes, the mapping for array variables is one-to-one. We support conditional mapping in this case, which can specify in the similar syntax as case (2), or you can use ` conditon ? var1 : var2 `. In the future, we may support using universal quantifier with indices for more complex mapping of arrays. +A memory expression allows more than a Verilog array name, because sometimes, the mapping for array variables is not one-to-one. We support conditional mapping in this case, you can specify it in the similar syntax as case (2), or you can use ` conditon ? var1 : var2 `. For an external memory, the mapping is actually between interface signals. The ILA array variables use 6 interface signals (see the table below) which should be mapped with the RTL signals. You can use refinement expression or condition-refinement pair for these signal mapping. Later, we shall see some examples of mapping internal or external arrays in ILA with either internal or external arrays in RTL. @@ -172,8 +164,7 @@ For an external memory, the mapping is actually between interface signals. The I | wdata | write data | -And the `interface mapping` is similar but there the key names are the ILA input variables. Currently, input variables with array type are not supported. - +The `input mapping` is similar to `state mapping` but there the keys are the ILA input variables. Currently, input variables with array type are not supported. ## Other Sections in Variable Mapping @@ -185,6 +176,8 @@ Within the same file of variable mapping, there are other sections: (1) clock an The interface mapping is used to specify which input port(s) is/are clock or reset signals. An example is shown below. The `CLOCK` field is a map from the name of the clock to the input pins. If there is only one clock, you can provide either a single input pin or multiple pin names in list which will be connected to the same clock. For reset, you can choose among the active-high/active-low or custom reset patterns using `RESET`, `NRESET` or `CUSTOMRESET`. +By default, all input ports are connected as the wrapper's input and all output ports are connected with the wrappper's output. In case you want to specify how the input ports should be connected, you can use the `INPUT PORTS` field. + ```javascript "RTL interface connection": { @@ -197,7 +190,10 @@ The interface mapping is used to specify which input port(s) is/are clock or res // the same single clock "RESET" : "reset", // you can have a list of signals here "NRESET" : ["nreset1", "nreset2"], // like this - "CUSTOMRESET" : {"name" : "input-pin", ...} + "CUSTOMRESET" : {"name" : "input-pin", ...}, + "INPUT PORTS" : { + "" : "" + } } ``` @@ -228,7 +224,7 @@ An example of the `reset` section is provided below. ``` The `clock` section is only needed if you have multiple clocks. Currently, the tool will only handle the case where the frequency of the clock signals have a least common multiple. Therefore, they can be simulated using a single clock signal. The `clock` tells the tool how to simulate this clock signal. -This can be specified using either `custom` or `factor` field. The `custom` field are sequences 0s and 1s where you can use the similar duplicate operator as in the custom sequence of reset configuration. Alternatively, you can use the `factor` section to specify how many cycles of 0s and 1s and the starting offset of each clock. +This can be specified using either `custom` or `factor` field. The `custom` field should be sequences of 0s and 1s where you can use the similar duplicate operator as in the custom sequence of reset configuration. Alternatively, you can use the `factor` section to specify how many cycles of 0s and 1s and the starting offset of each clock. An example of the `clock` section is provided below, where using the `factor` field and the `custom` field actually creates the same set of clock signals. @@ -356,7 +352,6 @@ The entering condition should explicitly have its previous stage in the conjunct "monitor" : { "tracker" : { // this is just a name "template" : "phase tracker", - "phases" : 4, "event-alias" : { // will be translated as creating 1-bit wire "issue" : "SomeVerilogExpressionsHere", // for example @@ -404,7 +399,6 @@ Additionally, you can declare alias for events which can be referred to in the r "monitor" : { "TrackingThroughFifo" : { // this is just a name "template" : "phase tracker", - "phases" : 2, "aux-var" : [ ["fifo_ptr", "reg", 8] ], "rules" : [ { // 1 @@ -429,7 +423,7 @@ Additionally, you can declare alias for events which can be referred to in the r } ``` -The phase tracker also allows specifying branching and convergence. This is useful, for example, in the verification of superscaler out-of-order processor implementation, where there are multiple pipelines and instructions can be dynamically dispatched to some processing pipelines. A phase can be referred to in other parts of the refinement specification using `#phase_name#`. +The phase tracker also allows specifying branching and convergence. This is useful, for example, in the verification of superscaler out-of-order processor implementation, where there are multiple pipelines and instructions can be dynamically dispatched to some processing pipelines. A phase can be referred to in other parts of the refinement specification using `#MonitorName_PhaseName#` (unnamed stages are named as `stageX` where X is the index in the list of rules, and the index starts from 0). #### Value Recoder @@ -469,9 +463,9 @@ assume property ((RTL.write_enable == 1) |-> ((r1_pvholder) == (RTL.registers[1] It creates an auxiliary Verilog variable `r1_pvholder` which carries a undetermined value. Its value keeps the same all the time, and an assumption says this undetermined value is same as the specified value `RTL.registers[1]`, under the condition that `RTL.write_enable == 1`. This variables can be referenced in other sections by `r1_pvholder`. This value holder does not check if there is only one cycle that `RTL.write_enable == 1` holds. If there are multiple cycles that its condition holds, the assumption may overconstrain if `RTL.registers[1]` should carry different values at these points. This situation should be avoided. -#### Abitrary Verilog +#### Arbitrary Verilog -You can also add arbitrary synthesizable Verilog as the monitor. An example is given below: +You can also add arbitrary synthesizable Verilog as the monitor. An example is shown below: ```javascript "monitor" : { @@ -491,7 +485,8 @@ This creates a 2-bit variable `counter` to count the number of cycles under a ce Monitors are normally only in effect when verifying instructions. If you want a monitor to appear also when verifying the invariants, you can add the `"keep-for-invariants":true` attribute in the monitor's description following the `defs` and `refs` attributes. - +Additionally, you can load Verilog from file using `"verilog-from-file":""` instead of the ` +verilog` field above. You can also have additional Verilog appended to the generated wrapper using field `append-verilog` and `append-verilog-from-file`. ## Instruction Completion Condition From 79f695b53046da8f114edcf69dffedfafdd751e8 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Fri, 26 Nov 2021 15:28:48 +0800 Subject: [PATCH 24/26] update doc --- verification/example.md | 16 ++++++++-------- verification/refinement.md | 2 +- verification/target.md | 24 ++++++++++-------------- 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/verification/example.md b/verification/example.md index 536efbb..4594e1b 100644 --- a/verification/example.md +++ b/verification/example.md @@ -16,9 +16,9 @@ When verifying the child-instructions, we need to map the state variables holdin ```javascript "state mapping": { - "ciphertext" : [["ILA.round == 0", "s_in" ], - ["ILA.round == 1", "s0" ], - ["ILA.round == 2", "s1" ], + "ciphertext" : [["ILA.round == 0", "RTL.s_in" ], + ["ILA.round == 1", "RTL.s0" ], + ["ILA.round == 2", "RTL.s1" ], ... ] } @@ -49,9 +49,9 @@ When tackling pipelined designs, for a software-visible state variable \(e.g., a ```javascript "state mapping": { ..., - "r1" : [ [ "m1.reg_1_w_stage[1]", "ex_alu_result"], - [ "m1.reg_1_w_stage[0]", "ex_wb_val" ], - [ "1'b1", "register[1]" ]], + "r1" : [ [ "m1.reg_1_w_stage[1]", "RTL.ex_alu_result"], + [ "m1.reg_1_w_stage[0]", "RTL.ex_wb_val" ], + [ "1'b1", "RTL.register[1]" ]], "r2" : [...], ... } @@ -66,8 +66,8 @@ Again for the previous pipeline example, we can have the variable mapping as fol ```javascript "state mapping": { ..., - "r1" : [ ["#decode#", "( m1.register[1] )@( stage_tracker == 1 )"], - ["#commit#", "register[1]"]], + "r1" : [ ["#decode#", "( RTL.register[1] )@( stage_tracker == 1 )"], + ["#commit#", "RTL.register[1]"]], "r2" : [...], ... } diff --git a/verification/refinement.md b/verification/refinement.md index e3ddae8..4498296 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -22,7 +22,7 @@ The top-level of a JSON file is a map and we call the key-value pairs in this to ## The Structure of Variable Mapping -Below shows the general structure of the variable mapping file (or in short, var-map). Each section (like `state mapping"`) will be explained in details later. Section `additional mapping`, `assumptions`, `monitor` and `functions` are optional. Section names are case-insensitive and you can always use hypen (`-`) to replace space in the section names. +Below shows the general structure of the variable mapping file (or in short, var-map). Each section (like `state mapping"`) will be explained in details later. Section `additional mapping`, `assumptions`, `monitor` and `functions` are optional. Section names are case-insensitive and you can always use hypen (`-`) or underscore (`_`) to replace space in the section names. ```javascript { diff --git a/verification/target.md b/verification/target.md index a13480d..a3e30b4 100644 --- a/verification/target.md +++ b/verification/target.md @@ -1,20 +1,16 @@ # Verification Target -The verification target can be generated by create a `VerilogVerificationTargetGenerator` object. Some prerequisites are: - -1. ILAng should be configured to have the switch `ILANG_INSTALL_DEV` turned on. -2. Include the header `ilang/vtarget-out/vtarget_gen.h` +The verification target can be generated by creating the `IlaVerilogRefinemetChecker` object. The arguments of the constructors are: -1. A list of paths to search for Verilog include files -2. A list of Verilog design files -3. The Verilog top module -4. The variable mapping file \(first part of refinement map\) -5. The instruction start/ready conditions \(second part of refinement map\) -6. The output path of the verification targets -7. The ILA model -8. The choice backend \(CoSA/JapserGold, the latter is not open-source and not included in the demo\) -9. \(Optional\) Target generator configuration -10. \(Optional\) Verilog generator configuration +1. The ILA object +2. A list of paths to search for Verilog include files +3. A list of Verilog design files +4. The Verilog top module +5. The variable mapping file \(first part of refinement map\) +6. The instruction start/ready conditions \(second part of refinement map\) +7. The output path of the verification targets +8. The choice of backend, which can be either `ModelCheckerSelection::JASPERGOLD` or `ModelCheckerSelection::PONO` +9. \(Optional\) Verilog generator configuration From 7f7a5f320c6b478e28d0a3422d931f5b8829c38c Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Tue, 30 Nov 2021 15:58:38 +0800 Subject: [PATCH 25/26] rfmap --- verification/refinement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verification/refinement.md b/verification/refinement.md index 4498296..3516a84 100644 --- a/verification/refinement.md +++ b/verification/refinement.md @@ -116,7 +116,7 @@ You can delay a signal by a fixed number of cycles using `signal ## cycle`. For If the RTL executes the instructions in multiple phases (e.g., pipeline stages), you will need to declare these phases in order to track the progression of the instruction and to find out its time of finish. This requires using phases trackers. By default, there are two built-in phase trackers: `#decode#` and `#commit#`. It is recommended to wrapped the phase trackers in a pair of `#`. -The specification of stages will be explain [later](#template-for-phase-identifier). +The specification of stages will be explain later. ## Module Naming From 176efc13da6b5d6289bb1a7930cefadf38add1b2 Mon Sep 17 00:00:00 2001 From: Hongce Zhang Date: Mon, 10 Jan 2022 11:29:47 +0800 Subject: [PATCH 26/26] Update target.md --- verification/target.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/verification/target.md b/verification/target.md index a3e30b4..2c8801f 100644 --- a/verification/target.md +++ b/verification/target.md @@ -1,6 +1,6 @@ # Verification Target -The verification target can be generated by creating the `IlaVerilogRefinemetChecker` object. +The verification target can be generated by creating the `IlaVerilogRefinementChecker` object. The arguments of the constructors are: @@ -14,3 +14,14 @@ The arguments of the constructors are: 8. The choice of backend, which can be either `ModelCheckerSelection::JASPERGOLD` or `ModelCheckerSelection::PONO` 9. \(Optional\) Verilog generator configuration +Some of the useful options are listed below (see `include/ilang/rtl_verify.h` for a full list): + + +| Option | Meaning | Possible values | +|---------------------|-----------------|-------------| +| ForceInstCheckReset | Whether to start from an arbitrary state | true/false | +| PonoEngine | Engines for Pono | "ind", "bmc", "ic3ia", "ic3sa", ... | +| PonoOtherOptions | Additional options for Pono | e.g., " -v 1 " sets verbose level to be 1. | +| YosysSmtArrayForRegFile | Whether to use SMT arrays for Verilog arrays | true/false | + +