Skip to content

Commit

Permalink
Add DFS approach for finalising states to derive different "currently…
Browse files Browse the repository at this point in the history
… false" vs "false", etc
  • Loading branch information
kiwih committed Jan 2, 2020
1 parent a363445 commit 8662330
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 6 deletions.
8 changes: 8 additions & 0 deletions rvc/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ type TemplateData struct {
//ConvertAll converts iec61499 xml (stored as []FB) into vhdl []byte for each block (becomes []VHDLOutput struct)
//Returns nil error on success
func (c *Converter) ConvertAll() ([]OutputFile, error) {

//first, finalise the states
for i := 0; i < len(c.Funcs); i++ {
for j := 0; j < len(c.Funcs[i].Policies); j++ {
c.Funcs[i].Policies[j].FinaliseStates()
}
}

finishedConversions := make([]OutputFile, 0, len(c.Funcs))

type templateInfo struct {
Expand Down
4 changes: 2 additions & 2 deletions rvc/rtecTemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ void {{$block.Name}}_run_via_monitor(monitorvars_{{$block.Name}}_t* me, io_{{$bl
uint8_t {{$block.Name}}_check_rv_status_{{$pol.Name}}(monitorvars_{{$block.Name}}_t* me) {
switch(me->_policy_{{$pol.Name}}_state) {
{{range $sti, $st := $pol.States}}case POLICY_STATE_{{$block.Name}}_{{$pol.Name}}_{{$st.Name}}:
{{if $st.Accepting}} {{if $pfbMon.Policy.GetTransitionsForSource $st.Name}} return 1; {{else}} return 0; {{end -}}
{{else}} {{if $pfbMon.Policy.GetTransitionsForSource $st.Name}} return 2; {{else}} return 3; {{end -}}
{{if $st.Accepting}} {{if $st.FinalStatusType}} return 0; {{else}} return 1; {{end -}}
{{else}} {{if $st.FinalStatusType}} return 3; {{else}} return 2; {{end -}}
{{end}}
{{end}}
}
Expand Down
5 changes: 3 additions & 2 deletions rvdef/rv.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ type Policy struct {

//PState is a state in the policy specification of an enforcerFB
type PState struct {
Name string
Accepting bool
Name string
FinalStatusType bool //if set to true, this stops being "currently xxx" and becomes just "xxx" when checking state
Accepting bool //if set to true, this returns "true" when checking state, if set to false, it returns "false"
}

//PTransition is a transition between PState in a Policy (mealy machine transitions)
Expand Down
67 changes: 67 additions & 0 deletions rvdef/rvFinaliseStates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package rvdef

//FinaliseStates will traverse the internal state machine of Policy p.
//It is responsible for setting the "true/false" value of the "Final" flag in all internal states
//(it does not care what they are currently set to, it will clear them all to "false" to begin with)
//States must be set to "Final=true" if no path exists to states of a different accepting kind.
// e.g one:
// s1(accepting) --> s2(nonaccepting) <----> s3(nonaccepting),
// s1 gets final=false, s2 gets final=true, s3 gets final=true,
// e.g. two:
// s4(accepting) --> s5(accepting) <----> s6(nonaccepting),
// s4, s5, s6 get final = false.
func (p *Policy) FinaliseStates() {
//reset all final flags
for i := 0; i < len(p.States); i++ {
p.States[i].FinalStatusType = false
}

//for each state, map out its possible destinations using a depth-first search approach
out:
for i := 0; i < len(p.States); i++ {
sourceState := p.States[i]
/* (from Wikipedia DFS)
// A non-recursive implementation of DFS with worst-case space complexity O(|E|):
procedure DFS-iterative(G, v) is
let S be a stack
S.push(v)
while S is not empty do
v = S.pop()
if v is not labeled as discovered then
label v as discovered
for all edges from v to w in G.adjacentEdges(v) do
S.push(w)
*/

S := make([]string, 0, 256) //for now assume 256 elements is enough, Go will add more if necessary
discoveredNames := make(map[string]bool)
S = append(S, p.States[i].Name)
for len(S) > 0 {
v := S[len(S)-1]
S = S[:len(S)-1]

//find the state
for j := 0; j < len(p.States); j++ {
if p.States[j].Name == v {
currentState := p.States[j]
if currentState.Accepting != sourceState.Accepting {
continue out //this is not a final status type state, we're done here
}
}
}
if discoveredNames[v] == false {
discoveredNames[v] = true

for _, t := range p.Transitions {
if t.Source == v {
if discoveredNames[t.Destination] == false {
S = append(S, t.Destination)
}
}
}
}
}
//if we couldn't find an escape, this is a Final Status state
p.States[i].FinalStatusType = true
}
}
4 changes: 2 additions & 2 deletions rvparser/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ func isValidType(s string) bool {
s == "int64_t" ||
s == "float" ||
s == "double" ||
s == "dtimer_t" ||
s == "rtimer_t" {
s == "dtimer_t" { //||
// s == "rtimer_t" { //rtimer is planned but not supported at this stage.
return true
}
return false
Expand Down

0 comments on commit 8662330

Please sign in to comment.