Commit a07b47a9 authored by Etienne Renault's avatar Etienne Renault

channels: fully supported

Note that even if channels are fully supported
by the scheduler, some syntax declaration element
are not supported

* boilerplate/main.go,
cspinfo/channel.go,
decl/decl.go,
main.go,
tests/prod_cons_simp.go,
transform/afterchannels.go,
transform/channels.go,
transform/meta.go: Here.
parent 65626262
......@@ -64,41 +64,63 @@ func G2PEntry(src G2PStateType) []G2PStateType {
result := append(res, G2PMain(src))
var final []G2PStateType = []G2PStateType{}
for i, _ := range result {
WAIT_READ := -1
WAIT_WRITE := 1
for _, succ := range result {
all_are_clear := true
var toadd []G2PStateType = []G2PStateType{}
for _, channel := range G2PChannels {
count := 0
WW, WR, place := make([]int, 0), make([]int, 0), make([]int, 0)
for j := channel.State; j < channel.State+channel.Length; j++ {
tmp := result[i][j]
if tmp == 1 {
count += tmp
WR = append(WR, j)
place = append(place, tmp)
} else if tmp == -1 {
count += tmp
WW = append(WW, j)
} else if tmp != 0 {
count += 1
WR = append(WR, j)
place = append(place, tmp)
}
}
if len(WW) > 0 && len(WR) > 0 {
for j := 0; j < len(WW); j++ {
result[i][WW[j]], result[i][WR[j]] = 0, 0
if place[j] != 1 {
result[i][place[j]] = result[i][channel.Value+(WW[j]-channel.State)]
for pid, idx := 0, channel.State; idx < channel.State+channel.Length; pid, idx = pid+1, idx+2 {
// There is sync in progress
if succ[idx] == WAIT_WRITE || succ[idx] == WAIT_READ {
all_are_clear = false
// Look for a sync. friend
if succ[idx] == WAIT_WRITE {
allclear1 := true
for jdx := channel.State; jdx < channel.State+channel.Length; jdx += 2 {
if succ[jdx] == WAIT_READ {
// build the combination of the 2
var new_succ G2PStateType = succ
// Reset WAIT_READ / WAIT_WRITE operations
new_succ[idx] = 0
new_succ[jdx] = 0
// Set the new successor
new_succ[new_succ[jdx+1]] = new_succ[idx+1]
// Reset Values
new_succ[idx+1] = 0
new_succ[jdx+1] = 0
toadd = append(toadd, new_succ)
}
}
// Other process can progress or this is the first step of sync.
if allclear1 {
if pid == 0 && ((src[1] == succ[1]) || (src[idx] != succ[idx])) {
toadd = append(toadd, succ)
} else if (src[G2PGoroutines[pid-1].LineCounter] == succ[G2PGoroutines[pid-1].LineCounter]) || src[idx] != succ[idx] {
toadd = append(toadd, succ)
}
}
}
}
}
if count >= 0 {
final = append(final, result[i])
}
// add successor and process the next successor
if all_are_clear {
final = append(final, succ)
} else if len(toadd) != 0 {
for _, e := range toadd {
final = append(final, e)
}
}
}
if len(G2PChannels) == 0 {
final = result
}
// Build the result by considering eventually RERS inputs
var final2 []G2PStateType = []G2PStateType{}
......
......@@ -22,6 +22,5 @@ package cspinfo
// representation inside go2pins
type Channel struct {
State int // index in vector of the beggining of State's array
Value int // index in vector of the beggining of Value's array
Length int // length of the arrays (same for the two)
Length int // length of the array (times two for both vectors)
}
......@@ -154,13 +154,6 @@ func Channel(c cspinfo.Channel) *ast.CompositeLit {
Value: strconv.Itoa(c.State),
},
},
&ast.KeyValueExpr{
Key: ast.NewIdent("Value"),
Value: &ast.BasicLit{
Kind: token.INT,
Value: strconv.Itoa(c.Value),
},
},
&ast.KeyValueExpr{
Key: ast.NewIdent("Length"),
Value: &ast.BasicLit{
......
......@@ -133,10 +133,12 @@ func compileTo(path string, src []byte, file *os.File,
}
res = transform.ApplyAll(f, meta, []transform.Transform{
&transform.Channel{},
&transform.Alive{},
&transform.Channel{
Goroutines: goroutines,
},
&transform.ArrayTreat{},
&transform.NormalizeDeclarations{},
&transform.Alive{},
&transform.ElseFull{},
&transform.ConditionnalCall{},
&transform.ArithmeticCall{},
......@@ -145,8 +147,8 @@ func compileTo(path string, src []byte, file *os.File,
&transform.RoutineAssignments{
Functions: goroutines,
},
&transform.AfterChannel{},
&transform.LocalVariableAssignments{},
&transform.AfterChannel{},
&cfg.Transform{},
&transform.RoutineCounter{
Functions: goroutines,
......@@ -155,35 +157,7 @@ func compileTo(path string, src []byte, file *os.File,
&transform.Format{},
})
templ, count := "", 0
tmpChan, tmpName, channels := cspinfo.Channel{}, "", []cspinfo.Channel{}
for i, elmt := range meta.GetVariables() {
if strings.Contains(elmt, "main_array_") {
if strings.Contains(elmt, "_state_") {
if templ == "" {
templ = elmt
tmpName = string(templ[11])
for _, str := range templ[12:] {
if string(str) == "_" {
break
} else {
tmpName += string(str)
}
}
tmpChan.State = i
count++
} else {
count++
}
} else if strings.Contains(elmt, "_value_0") {
tmpChan.Value = i
tmpChan.Length = count
}
} else if elmt == "main_isalive_"+tmpName+"_value" {
channels = append(channels, tmpChan)
templ, count = "", 0
}
}
var channels = meta.GetChans()
// Generate all the cases of the main switch case.
cases := make([]ast.Stmt, len(meta.GetFunctions())+1)
......
......@@ -18,13 +18,19 @@
package main
func producer(com chan int) {
com <- 1
var com chan int = make(chan int)
func producer() {
com <- 51
}
func main() {
com := make(chan int)
go producer(com)
a := <-com
func cons() {
a := 42
a = <-com
a = a + 1
}
func main() {
go producer()
cons()
}
......@@ -20,68 +20,40 @@ package transform
import (
"go/ast"
"go/token"
"strconv"
"strings"
)
/*
The AfterChannel is a hack that remove _g2p_chan_to_remove in order
to access information not aivalable at the time of processing channels.
Transform :
Before:
```
G2PState[1] = _g2p_chan_to_remove + G2PState[18]
```
After:
```
G2PState[1] = 18
```
*/
type AfterChannel struct {
currentFunc *ast.Object
}
// Pre traversal
func (t *AfterChannel) Pre(meta *Meta, v *Visitor) bool {
c := v.Cursor()
switch node := c.Node().(type) {
case *ast.AssignStmt:
newAssign := &ast.AssignStmt{
Lhs: []ast.Expr{},
Tok: node.Tok,
Rhs: []ast.Expr{},
}
do := false
for i, elmt := range node.Lhs {
switch elmt := elmt.(type) {
case *ast.Ident:
name := elmt.Name
if strings.Contains(name, "array_") && strings.Contains(name, "_state_") {
switch rhn := node.Rhs[i].(type) {
case *ast.Ident:
index := meta.StateSize()
obj := rhn.Obj
meta.GetOrAdd(obj, v.Name(), t.currentFunc)
node.Rhs[i] = &ast.BasicLit{
Kind: token.INT,
Value: strconv.Itoa(index),
}
}
}
}
switch rhn := node.Rhs[i].(type) {
case *ast.UnaryExpr:
switch rhn.X.(type) {
case *ast.Ident:
if rhn.Op == token.ARROW {
do = true
} else {
newAssign.Lhs = append(newAssign.Lhs, elmt)
newAssign.Rhs = append(newAssign.Rhs, rhn)
}
case *ast.BinaryExpr:
switch tmp := node.X.(type) {
case *ast.Ident:
if tmp.Name == "_g2p_chan_to_remove" {
switch tmp2 := node.Y.(type) {
case *ast.IndexExpr:
c.Replace(tmp2.Index)
}
default:
newAssign.Lhs = append(newAssign.Lhs, elmt)
newAssign.Rhs = append(newAssign.Rhs, rhn)
}
}
if do {
if len(node.Lhs) > 1 {
c.Replace(newAssign)
} else {
c.Delete()
}
}
case *ast.FuncDecl:
t.currentFunc = node.Name.Obj
}
return true
}
......
This diff is collapsed.
......@@ -23,6 +23,8 @@ import (
"go/token"
"go/types"
"strconv"
"gitlab.lrde.epita.fr/spot/go2pins/cspinfo"
)
type objectRecord struct {
......@@ -81,6 +83,12 @@ type array struct {
size int
}
type channel struct {
name string
obj *ast.Object
size int
}
// Meta represents all metadata kept around during the transform steps.
type Meta struct {
fset *token.FileSet
......@@ -95,6 +103,7 @@ type Meta struct {
functions map[*ast.Object]*FunctionRecord
functionsSlice []*FunctionRecord
arrays []*array
channels []*channel
}
// NewMeta returns a new Meta structure.
......@@ -294,6 +303,30 @@ func (m *Meta) RegisterArray(name string, ident string, size int) {
})
}
// Channels and Arrays are processed identically. Except that channels
// also register elsewhere for latter access.
func (m *Meta) RegisterChannel(obj *ast.Object, name string, ident string, size int) {
m.RegisterArray(name, ident, size)
m.channels = append(m.channels, &channel{
name: name,
obj: obj,
size: size,
})
}
func (m *Meta) GetChans() []cspinfo.Channel {
var channels = []cspinfo.Channel{}
for _, e := range m.channels {
rec := m.objs[e.obj]
element := cspinfo.Channel{
State: rec.idx,
Length: e.size,
}
channels = append(channels, element)
}
return channels
}
// Returns the size of the registered array or 0
func (m *Meta) is_registered_array(name string, ident string) int {
for _, e := range m.arrays {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment