Using implication operator for different address ranges - system-verilog

I am wondering how implication operator can be used if I want to choose between different address ranges. I am using if/else condition, but it seems constraint solver is not accepting any solution for this.
constraint ctCopy { mode == C_CMD -> if (addr_range == "DST_SRAM") {dstAddr inside {[0:'hFFFF]}; }
else if (addr_range == "DST_AXI") {dstAddr inside {['h30000:'h3FFFF]}; }
else if (addr_range == "DST_AHB") {dstAddr inside {[20000:'h2FFFF]}; }
else {dstAddr inside {[0:'hFFFF]}; }
mode == C_CMD -> if (addr_range == "SRC_SRAM") {srcAddr inside {[0:'hFFFF]}; }
else if (addr_range == "SRC_AXI") {srcAddr inside {[0:'h30000]}; }
else {srcAddr inside {[0:'hFFFF]}; }
mode == C_CMD -> cSize inside {[2:10]} ;
}
I am trying to use with constraint, but solver does not accept. Here is the snippet:
Trn0.randomize() with { mode == C_CMD; addr_range == "DST_AHB";};
small example to reproduce is as below
class top;
rand logic [3:0] mode;
rand logic [16:0] dstAddr;
rand logic [16:0] srcAddr;
string addr_range;
rand logic [4:0] copySize;
constraint ctCopy { mode == 1 -> if (addr_range == "DST_SRAM") {dstAddr inside {[0:'hFFFF]}; }
else if (addr_range == "DST_AXI") {dstAddr inside {['h30000:'h3FFFF]}; }
else if (addr_range == "DST_AHB") {dstAddr inside {[20000:'h2FFFF]}; }
else {dstAddr inside {[0:'hFFFF]}; }
mode == 1 -> if (addr_range == "SRC_SRAM") {srcAddr inside {[0:'hFFFF]}; }
else if (addr_range == "SRC_AXI") {srcAddr inside {[0:'h30000]}; }
else {srcAddr inside {[0:'hFFFF]}; }
mode == 1 -> copySize inside {[2:10]} ;
}
endclass
module tb;
initial begin
top tb = new;
tb.randomize() with { mode == 1; addr_range == "DST_AHB";};
$display("dstAddr=%0d,srcAddr=%0d",tb.dstAddr,tb.srcAddr);
end
endmodule
Self contained example at:
https://www.edaplayground.com/x/rjZy

addr_range is of type string, which means it can not be a rand variable. One way to fix your problem is to set addr_range before you call randomize:
module tb;
initial begin
top tb = new;
tb.addr_range = "DST_AHB";
tb.randomize() with { mode == 1; };
$display("dstAddr=%0d,srcAddr=%0d",tb.dstAddr,tb.srcAddr);
end
endmodule
Another way is to use enums instead of strings if you want addr_range to be random.
When you run with Cadence on edaplayground, it generates warning messages about some of the values in your constraint being out of range. For example, you declared dstAddr as a 17-bit value, but 'h3FFFF requires at least 18 bits. You should fix your values.

Related

Swift Scope - Returning if and for results from a function

How do i get the result of of i to return from the function here? I can return it from inside the if { } but then I get an error there’s no global return (for the function). My goal is to write a function that accepts an Integer and returns the square root. My next step is to throw an error if it's not an Int or between 1 and 10,000, but please assume simple numbers for this question.
let userInputInteger = 9
func squareRootCheckpoint4(userInputInteger: Int) -> Int {
for i in 1...100 {
let userInputInteger = i * i
if i == userInputInteger {
break
}
}
return i
}
update:
To be able to return it, you will have to declared a variable outside the for-loop, then based on the logic assign the "i" counter to that outside variable.
func squareRootCheckpoint4(userInputInteger: Int) -> Int {
var result = 0 // this is to keep the result
for i in 1...100 {
let powerOfTwoResult = i * i
if powerOfTwoResult == userInputInteger {
result = i // assign result variable based on the logic
break
}
}
return result // return result
}
The error shown is because if the for-loop finishes without any hit on the if statement, the function will not be able to return any Int. That's why the compiler produces that "no global return" error.
One way to do it if you don't want to return a default value is to throw an error. You could throw an error from a function (https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html). For example for your goal of returning square root of an integer and throw error if the input integer is not between 1 and 10000 (if I understand correctly), you could do something like this
enum InputError: Error {
case invalidInteger
}
func squareRootCheckpoint4(userInputInteger: Int) throws -> Int {
if userInputInteger < 1 || userInputInteger > 10000 {
throw InputError.invalidInteger
}
// calculate square root
return resultOfSquareroot
}
// and to handle the error, you could encapsulate the squareRootCheckpoint4 function in a do-catch statement
do {
let squareRootResult = try squareRootCheckpoint4(userInputInteger: 4)
} catch InputError.invalidInteger {
// handle your error here
}
Alternatively, you could do a validation on the input integer separately before calling the squareRootCheckpoint4 function. For example
func validate(_ input: Int) -> Bool {
if userInputInteger < 1 || userInputInteger > 10000 {
return false
}
return true
}
func squareRootCheckpoint4(userInputInteger: Int) -> Int {
// calculate square root
return resultOfSquareroot
}
var input: Int = 9
if validate(input) {
let squareRootResult = squareRootCheckpoint4(input)
} else {
// handle when input is invalid
}
A couple of things are swapped around, and something (anything) needs to be returned from the function. The framing of the question only allows solutions that don't work if the input is not an integer with a square root.
List of Specifics:
The function argument name userInputInteger should not have been used to instantiate a new object. That's confusing. I did it because I'm learning and thought it was necessary.
Instead, i times i (or i squared) should have been assigned to a new object.
The if statement should be equal to this new object, instead of i.
Functions should return something. When i is returned in the if statement, it's not available anywhere outside the for loop. The print statements in the code example help explain what is available in these different scopes, as well as what's not.
The for loop stops when i is returned. That happens when the guess (i) is equal to the input (userInputInteger).
The for loop will continue through 100 if the input doesn't have a square root.
The function should return the correct number that the if statement was trying to guess, but you have to tell it to (with a return statement) and do it in the right spot. This is the "global return" error. However, because this approach in the question is setup poorly without error handling, only an Integer with a sqare root will return correctly. And in this case, the function's global return doesn't matter; Swift just requires something be returned, regardless of whether or not it's used.
Code Example - Direct Answer:
import Cocoa
let userInputInteger = 25
let doesNotMatter = 0
print("sqrt(\(userInputInteger)) is \(sqrt(25))") //correct answer for reference
func squareRootCheckpoint4(userInputInteger2: Int) -> Int {
var j: Int
for i in 1...100 {
print("Starting Loop \(i)")
j = i * i
if j == userInputInteger2 {
print("i if-loop \(i)")
print("j if-loop \(j)")
return i
}
print("i for-loop \(i)")
print("j for-loop \(j)")
}
//print("i func-end \(i)") //not in scope
//print("j func-end \(j)") //not in scope
//return i //not in scope
//return j //not in scope
print("Nothing prints here")
// but something must be returned here
return doesNotMatter
}
print("Input was \(userInputInteger)")
print("The Square Root of \(userInputInteger) is \(squareRootCheckpoint4(userInputInteger2: userInputInteger))")
Code Example - Improved with Error Handling
import Cocoa
enum ErrorMsg : Error {
case outOfBoundsError, noRootError
}
func checkSquareRoot (Input userInputInteger2: Int) throws -> Int {
if userInputInteger < 1 || userInputInteger > 10_000 {
throw ErrorMsg.outOfBoundsError
}
var j : Int
for i in 1...100 {
print("Starting Loop \(i)")
j = i * i
if j == userInputInteger2 {
print("i if-loop \(i)")
print("j if-loop \(j)")
return i
}
print("i for-loop \(i)")
print("j for-loop \(j)")
}
throw ErrorMsg.noRootError
}
let userInputInteger = 25
print("Input was \(userInputInteger)")
do {
let result = try checkSquareRoot(Input: userInputInteger)
print("The Square Root of \(userInputInteger) is \(result)")
} catch ErrorMsg.outOfBoundsError {
print("out of bounds: the userInputInteger is less than 1 or greater than 10,000")
} catch ErrorMsg.noRootError {
print("no root")
}
print("Swift built-in function for reference: sqrt(\(userInputInteger)) is \(sqrt(25))") //correct answer for reference

Randomization of a parameterized class inside a class not working

I am trying to use a parameterized class inside another class which I have to randomize.
typedef enum logic [1:0] {
TWO_LEGS,
FOUR_LEGS,
SIX_LEGS,
EIGHT_LEGS
} leg_e;
typedef enum logic [2:0] {
HUMAN,
DOGS,
CAT,
ELEPHANT,
FLY,
COCKROACH,
SPIDER
} animal_e;
class parameterized_class #( type enum_type);
static int initial_allocation;
static enum_type list[$];
rand int unsigned ptr;
constraint ptr_c {
ptr < list.size();
}
function new();
enum_type my_enum;
if(initial_allocation == 0) begin
initial_allocation = 1;
for(int unsigned i = 0; i < my_enum.num(); i++)
repeat($urandom_range(1,10)) list.push_back(my_enum);
end
endfunction
endclass
class random_class;
rand parameterized_class#(leg_e) leg_select;
rand parameterized_class#(animal_e) animal_select;
rand leg_e leg_q[$];
rand animal_e animal_q[$];
constraint leg_animal_c {
leg_select.list[leg_select.ptr] == TWO_LEGS -> animal_select.list[animal_select.ptr] inside {HUMAN};
leg_select.list[leg_select.ptr] == FOUR_LEGS -> animal_select.list[animal_select.ptr] inside {DOGS, CAT, ELEPHANT};
leg_select.list[leg_select.ptr] == SIX_LEGS -> animal_select.list[animal_select.ptr] inside {FLY, COCKROACH};
leg_select.list[leg_select.ptr] == EIGHT_LEGS -> animal_select.list[animal_select.ptr] inside {SPIDER};
}
constraint q_c {
leg_q.size() dist {[0:5] := 50, [6:10] := 50};
animal_q.size() == leg_q.size();
foreach(leg_q[i]) {
leg_q[i] == leg_select.list[leg_select.ptr];
animal_q[i] == animal_select.list[animal_select.ptr];
}
}
function new();
leg_select = new;
animal_select = new;
endfunction
endclass
module tb;
initial begin
random_class rnd = new;
repeat (10) begin
rnd.randomize();
$display("Animals in queue = %p", rnd.animal_q);
$display("Legs in queue = %p", rnd.leg_q);
end
end
endmodule
I am getting an error:
The solver will not solve for array 'animal_select.list' indexed by random
variable 'animal_select.ptr'.
Please try to use a state variable, constant, or loop variable for array
index.
What modification I havee to make to get a result like:
{DOGS, CAT, HUMAN, ELEPHANT}
{FOUR_LEGS, FOUR_LEGS, TWO_LEGS, FOUR_LEGS, }
I think you might be over-thinking your problem. I think this code produces the result you are hoping for:
typedef enum logic [1:0] {
TWO_LEGS,
FOUR_LEGS,
SIX_LEGS,
EIGHT_LEGS
} leg_e;
typedef enum logic [2:0] {
HUMAN,
DOGS,
CAT,
ELEPHANT,
FLY,
COCKROACH,
SPIDER
} animal_e;
class random_class;
rand leg_e leg_q[$];
rand animal_e animal_q[$];
constraint leg_animal_c {
foreach (leg_q[i]) leg_q[i] == TWO_LEGS -> animal_q[i] inside {HUMAN};
foreach (leg_q[i]) leg_q[i] == FOUR_LEGS -> animal_q[i] inside {DOGS, CAT, ELEPHANT};
foreach (leg_q[i]) leg_q[i] == SIX_LEGS -> animal_q[i] inside {FLY, COCKROACH};
foreach (leg_q[i]) leg_q[i] == EIGHT_LEGS -> animal_q[i] inside {SPIDER};
}
constraint q_c {
leg_q.size() dist {[0:5] := 50, [6:10] := 50};
animal_q.size() == leg_q.size();
}
endclass
module tb;
initial begin
random_class rnd = new;
repeat (10) begin
rnd.randomize();
$display("Animals in queue = %p", rnd.animal_q);
$display("Legs in queue = %p", rnd.leg_q);
end
end
endmodule
https://www.edaplayground.com/x/3rh8
I put a $diplay() debug in your code
foreach (list[i]) $display(list[i].name());
and see that your initialization is wrong. You always push the first enum into the list.
I changed your code to
for(int unsigned i = 0; i < my_enum.num(); i++) begin
/*repeat($urandom_range(1,10))*/ list.push_back(my_enum);
my_enum = my_enum.next();
end
and it does work. EDA code here.
And why do all the queues have identical elements, it is because of your constraints
foreach(leg_q[i]) {
leg_q[i] == leg_select.list[leg_select.ptr];
animal_q[i] == animal_select.list[animal_select.ptr];
}

Swift 3 enum with associated value AND function comparison

I have this struct that has an enum property as well as a function:
struct UserInput {
enum State {
case unrestricted
case restricted(because: WarningType)
enum WarningType {
case offline
case forbidden
}
}
var config: UserInputConfig?
var state: State = .unrestricted
func isConfigured() -> Bool {
// Arbitrary checks about the config...
}
}
Is there a way to rewrite the following conditionals so that the check for isConfigured() and state are in the same statement?
if case .restricted = userInput.state {
return 1
} else if userInput.isConfigured() {
return 1
} else {
return 0
}
It seems because the State enum uses associated values, you cannot simply write if userInput.state == .restricted || userInput.isConfigured(), you need to use the if case syntax. There must be a way around this?
You would like to do this:
if case .restricted = userInput.state || userInput.isConfigured() {
return 1
} else {
return 0
}
but there is currently no way to do an OR with pattern matching. There are a couple of ways of doing AND.
By using DeMorgan's Laws, you can turn if a || b into if !(!a && !b) and by reversing the then and else clauses of your if statement, you can just check for if !a && !b.
Unfortunately, you can't say if !(case .restricted = userInput.state), but since your enum has only 2 cases, you can replace that with if case .unrestricted = userInput.state.
Now, how do you use that with another statement? You can't use && for the same reason you can't use ||.
You can check for the failing case by using a pattern that matches both failing conditions (which is using AND) and then return 1 if both failing conditions aren't met:
if case (.unrestricted, false) = (userInput.state, userInput.isConfigured()) {
return 0
} else {
return 1
}
Equivalently you can use a multi-clause condition:
if case .unrestricted = userInput.state, !userInput.isConfigured() {
return 0
} else {
return 1
}
In addition to being shorter and IMO easier to read, this second method can short circuit and skip calling userInput.isConfigured in the case where case .unrestricted = userInput.state fails.
You can do it really cleanly with a switch statement, and pattern matching:
switch userInput.state
{
case .unrestricted:
return userInput.isConfigured() ? 1 : 0;
case .restricted(_):
return 1
}

Are "&&" and "," the same in Swift?

As the title says, I just came across a case where if && (AND) and , give the same result in Swift. I tested the code below:
let a = 5
let b = 6
if a<6, b>0 {
print("should be true")
}
if a<6, b<0 {
print("should be false")
}
if a>6, b>0 {
print("should be false")
}
if a>6, b<0 {
print("should be false")
}
It only logs:
should be true
So, the behavior of , is just like &&, am I correct?
They can be used in similar situations but that does not mean they are exactly the same.
Consider:
if (a && b) || c
you cannot write
if (a, b) || c
even a && b || c is different from a, b || c.
if a, b is something like
if a {
if b {
...
}
}
Both expressions have to be evaluated to true but they are still two separate expressions. We shouldn't imagine && there.
Why do we need the , operator?
The operator is needed to combine optional binding with boolean conditions, e.g.
if let a = a, a.isValid() {
becuase && wouldn't help us in such situations.
They're different in that a comma will take the lowest precedence possible. i.e everything else will be executed before the commas are checked.
// (true || false) && false
if true || false, false {
print("I will never be executed")
}
// true || (false && false)
if true || false && false {
print("I am always executed")
}

I am trying to update my for loop for Swift 3 and I can't figure it out. I keep getting errors

This is my original function in Swift 2:
// check on winning combinations
func checkWinnerMove(){
for var i = 0; i<winningCombinations.count && !isWinner;i += 1 {
if gameState[winningCombinations[i][0]-1] == activePlayer &&
gameState[winningCombinations[i][1]-1] == activePlayer &&
gameState[winningCombinations[i][2]-1] == activePlayer{
isWinner = true;
}else{
isWinner = false;
}
}
}
I have changed it to this:
// check on winning combinations
func checkWinnerMove(){
for i in 0 ..< winningCombinations.count && !isWinner{
if gameState[winningCombinations[i][0]-1] == activePlayer &&
gameState[winningCombinations[i][1]-1] == activePlayer &&
gameState[winningCombinations[i][2]-1] == activePlayer{
isWinner = true;
}else{
isWinner = false;
}
}
}
But keep getting a error when I add the
&& !isWinner
statment in the for-in loop. The error I get is:
No '..<' candidates produce the expected contextual result type 'Bool'
Any suggestions? Thank You!
Instead of forcibly trying to rewrite your original C-style for loop, consider what you're trying to achieve and attempt to re-write it in "native" Swift from scratch. How about breaking out of your loop once your true condition is met, instead of keeping it in the loop signature? E.g.
for i in 1...5 {
print(i)
if i == 3 { break }
} // 1 2 3
Applied to your example
func checkWinnerMove()
isWinner = false
for i in 0 ..< winningCombinations.count {
if gameState[winningCombinations[i][0]-1] == activePlayer &&
gameState[winningCombinations[i][1]-1] == activePlayer &&
gameState[winningCombinations[i][2]-1] == activePlayer {
isWinner = true
break
}
}
}
The explicit by index access of the (unknown for us) gameState and winningCombinations sequences is quite "unswifty" w.r.t. in the dangers of runtime exceptions for indices out of range for the sequences. So bear in mind that there are safer ways to perform such access.
For future reference, consider reading How to create a Minimal, Complete, and Verifiable example: since we (the potential answerer's of your question) don't have access to/the full information regarding isWinner, winningCombinations, gameState or activePlayer, we can't verify your example. Also, since the question cover a concept, it could be boiled down to a more minimal form. (Welcome to StackOverflow!)